// 2. System definitions #define Timer_WholeLine F_CPU/15625 //One PAL line 64us #define Timer_HalfLine Timer_WholeLine/2 //Half PAL line = 32us #define Timer_ShortSync Timer_WholeLine/32 //2us #define Timer_LongSync Timer_ShortSync*15 //30us #define Timer_NormalSync Timer_WholeLine/16 //4us #define Timer_blank Timer_WholeLine/8 //8us //Global definitions for render PAL #define PAL_FPS 50 #define pal_first_visible_line1 40 #define pal_last_visible_line1 290 //pal_first_visible_line1+pal_row_count*pal_symbol_height #define horiz_shift_delay 15
// Initialize Sync for PAL synccount = 1; VIDEO_DDR |= (1<<SYNC_PIN); OCR1B = Timer_LongSync; TCCR1A = (1<<COM1B1)|(1<<COM1B0)|(0<<WGM10)|(1<<WGM11); //Fast PWM,Set OC1B on Compare Match, // clear OC1B at BOTTOM (inverting mode) TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10); //full speed;TOP = ICR1 ICR1 = Timer_HalfLine; // . TIMSK1 = (1<<OCIE1B); //enable interrupt from row_render=0; y_line_render=0;
// volatile unsigned int synccount; // EMPTY_INTERRUPT (TIMER1_COMPB_vect); void MakeSync(void) { switch (synccount) { case 5://++++++++++++++++++++++++++++++++++++++++++++++++++++++++= Sync=Timer_ShortSync; synccount++; break; case 10://++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ICR1 = Timer_WholeLine; Sync= Timer_NormalSync; synccount++; break; case 315://++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ICR1 = Timer_HalfLine; Sync= Timer_ShortSync; synccount++; break; case 321://++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Sync=Timer_LongSync; synccount=1; framecount++; linecount = 0; break; default://++++++++++++++++++++++++++++++++++++++++++++++++++++++++ synccount++; video_enable_flg = ((synccount>pal_first_visible_line1)&&(synccount<pal_last_visible_line1)); break; } }
#define SPI_PORT PORTB #define SPI_DDR DDRB #define MOSI PORTB3 #define MISO PORTB4 #define SCK PORTB5 // #define VIDEO_PORT SPI_PORT #define VIDEO_DDR SPI_DDR #define VIDEO_PIN MOSI #define VIDEO_OFF DDRB=0b00100100; #define VIDEO_ON DDRB=0b00101100;
//Set SPI PORT DDR bits VIDEO_DDR |= (1<<MOSI)|(1<<SCK)|(0<<MISO); SPSR = 1 << SPI2X; SPCR = (1 << SPE) | (1 << MSTR); //SPI enable as master ,FREQ = fclk/2
inline void DrawString (unsigned char *str_buffer[], struct FONT_INFO *font, unsigned char str_symbols) { unsigned char symbol_width; unsigned char i; unsigned char * _ptr; unsigned char * _ptr1; y_line_render++; //Set pointer for render line (display buffer) _ptr = &str_buffer[row_render * str_symbols]; unsigned char j; register unsigned char _S; unsigned char _S1; //Cycle for render line i = str_symbols; while(i--) { symbol_width = font->width[(* _ptr)]; //Set pointer for render line (character generator) _ptr1 = &font->bitmap[font->offset[* _ptr]+y_line_render*symbol_width]; _S1 = 0; // _S = pgm_read_byte(_ptr1); // _ptr1++; j=symbol_width; // while (1) { if (_S1 & 0b1) { goto matr; } VIDEO_OFF; matr: NOP; SPDR = _S; VIDEO_ON; _S1 = _S; _S = pgm_read_byte(_ptr1++); NOP; NOP; if (!--j) break; } _ptr++; VIDEO_OFF; } }
// Character bitmaps for Digital-7 Mono 120pt const unsigned char PROGMEM Digital7_Bitmaps[] = { // @0 '0' (71 pixels wide) 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x80, // ############################################# # 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xE0, // ############################################### ### 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xF0, // ############################################### ##### 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xF8, // ################################################ ###### ... ... } const unsigned char Digital7_Height = 105; const unsigned char Digital7_Width[] = { 9, /* 0 */ 9, /* 1 */ 9, /* 2 */ 9, /* 3 */ 9, /* 4 */ 9, /* 5 */ 9, /* 6 */ 9, /* 7 */ 9, /* 8 */ 9, /* 9 */ 3 /* : */ }; const unsigned int Digital7_Offset[] = { 0 , /* 0 */ 945, /* 1 */ 1890, /* 2 */ 2835, /* 3 */ 3780, /* 4 */ 4725, /* 5 */ 5670, /* 6 */ 6615, /* 7 */ 7560, /* 8 */ 8505, /* 9 */ 9450 /* : */ };
unsigned char clock_left; bool clock_set; volatile unsigned char MinTens, MinOnes; volatile unsigned char SecTens, SecOnes; static void pal_terminal_handle(void) { unsigned char received_symbol = 0; // Parser received symbols from UART while(UCSR0A & (1<<RXC0)) { received_symbol = UDR0; if (received_symbol=='#') { clock_left=5; clock_set = true; } if ((received_symbol>0x2F)&&(received_symbol<0x3A)) { if (clock_set) { time_array[5-clock_left] = received_symbol - 0x30; clock_left--; if (clock_left==3) { clock_left--; } if (clock_left==0) { time_array[6] = 0; time_array[7] = 0; clock_set = false; } } else { if ((pause==0)||_Stop) { MinTens = 0; } else { MinTens = MinOnes; } MinOnes = received_symbol - 0x30; SecTens = 0; SecOnes = 0; pause = 4; _Stop = false; str_array[0] = MinTens; str_array[1] = MinOnes; str_array[2] = 0x0A; str_array[3] = SecTens; str_array[4] = SecOnes; } //time_array[] = {1, 2, 10, 5, 5}; } } }
volatile bool _Stop; struct FONT_INFO { unsigned char height; unsigned char * bitmap; unsigned int * offset; unsigned char * width; } Digital7, comdot; int main(void) { avr_init(); //fonts Digital7.bitmap = &Digital7_Bitmaps; Digital7.height = Digital7_Height; Digital7.offset = &Digital7_Offset; Digital7.width = &Digital7_Width; comdot.bitmap = &comdotshadow_Bitmaps; comdot.height = comdotshadow_Height; comdot.offset = &comdotshadow_Offset; comdot.width = &comdotshadow_Width; MinTens = 0; MinOnes = 0; SecTens = 0; SecOnes = 0; str_array[0] = MinTens; str_array[1] = MinOnes; str_array[2] = 0x0A; str_array[3] = SecTens; str_array[4] = SecOnes; unsigned char *semicolon = &time_array[2]; sei(); while (1) { sleep_mode(); MakeSync(); if (UCSR0A & (1<<RXC0)) { //Parse received symbol pal_terminal_handle(); //Can easealy add here RX polling buffer //to avoid display flickering continue; } //Check visible field if(video_enable_flg) { linecount++; //OK, visible //Main render routine #define firstline 36 #define secondline 200 //To make horizontal shift rendered image unsigned char k; for (k=horiz_shift_delay; k>0; k--) { NOP; } if ((linecount == firstline)||(linecount == secondline)) { row_render = 0; y_line_render = 0; } if ((linecount> firstline) && (linecount< firstline+(Digital7.height))) { DrawString(&str_array, &Digital7, 5); } if ((linecount> secondline) && (linecount< secondline+(comdot.height))) { DrawString(&time_array, &comdot, 5); } } else { //Not visible //Can do something else.. //You can add here your own handlers.. // VIDEO_OFF; if (framecount==PAL_FPS) { framecount=0; //========================================= if (*semicolon== 11) { *semicolon=10; } else { *semicolon=11; } if (++time_array[7] == 10) { framecount = 1;// time_array[7]=0; if (++time_array[6]==6) { framecount = 3; // time_array[6]=0; if (++time_array[4]==10) { time_array[4]=0; if (++time_array[3]==6) { time_array[3]=0; if ((++time_array[1]==4) && (time_array[0]==2)) { time_array[0]=0; time_array[1]=0; } if (time_array[1]== 9) { time_array[1]=0; time_array[0]++; } } } } } //========================================= if ((pause==0)&&(_Stop==false)) { if ((SecOnes--)==0) { SecOnes=9; if ((SecTens--) == 0) { SecTens = 5; if ((MinOnes--) == 0) { MinOnes = 9; if (MinTens == 0) { _Stop = true; } else { MinTens--; } } } } if (!_Stop) { str_array[0] = MinTens; str_array[1] = MinOnes; str_array[2] = 0x0A; str_array[3] = SecTens; str_array[4] = SecOnes; } } else { pause--; } } } } }
Source: https://habr.com/ru/post/301598/
All Articles