/* Electronic Instant Camera runs on an ATMEGA8 with 16MHz, program is written in AVR-GCC The program digitizes single lines of a PAL video image and prints them out on a thermal receipt printer. The circuit requires an additional LM1881 for sync signal separation. * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return Niklas Roy * ---------------------------------------------------------------------------- As usual: Sorry for too less coments and crappy coding skills */ #include #include #include #include #include #define MX1 PORTD=0b10100000; #define MX2 PORTD=0b01100000; #define MX3 PORTD=0b01010010; #define MX4 PORTD=0b10010000; uint8_t sync_count=0; uint8_t scan[500]; //samples of each uint8_t xpos; uint8_t dither=5; volatile uint8_t new_frame_flag; volatile uint8_t new_sample_flag; volatile uint16_t video_line=0; //lines of video image volatile uint8_t video_column=119; volatile uint8_t sample; uint8_t p_sample=0; uint8_t p2_sample=0; uint8_t n_sample=0; //////////////////////////////////////////////////////////////// MAIN ///////////////////////////// int main(void) { //IO DDRB = 0b00011110; // b1-4 pixel DDRC = 0b00001111; // c0-3 mot y DDRD = 0b11110000; // d4-7 mot x _delay_us(2); //Pull Up's / Outputs PORTB= 0b00000001; //button pb0 PORTC= 0b00010000; //button c4 PORTD= 0b00000000; ADCSRA=0b10000011; // ADC Enable, Free running, Divide 16 ADMUX= 0b00100101; // ADC ext. Voltage reference / result=1byte, select ADC5 for (uint8_t i=0;i< 56;i++){ //motx right to calibrate PORTD=0b10100000; _delay_ms(4); PORTD=0b01100000; _delay_ms(4); PORTD=0b01010010; _delay_ms(4); PORTD=0b10010000; _delay_ms(4); } for (uint8_t i=0;i< 56;i++){ //motx left to origin PORTD=0b10010000; _delay_ms(4); PORTD=0b01010000; _delay_ms(4); PORTD=0b01100000; _delay_ms(4); PORTD=0b10100000; _delay_ms(4); } PORTD=0b00000000; _delay_ms(100);//motx off //printer form feed for (uint8_t i=0;i<70;i++){ //paper out y ///////////////////////////////////////////////// if (i==36){ PORTC=0b00000000; _delay_ms(1);//moty off for (uint16_t i=5;i<227;i++) //dotted line { xpos++; switch (xpos%4) //move printhead { case 0: MX1 break; case 1: MX2 break; case 2: MX3 break; case 3: MX4 break; } if ((i%9)>3) PORTB= 0b00000010; //1 pixel on _delay_ms(3); PORTB= 0b00000000; //0 pixel on _delay_ms(1); if (!(i%9))i++; //kick out some loops to match scanned image on paper } PORTB= 0b00000000; //all pixel off while (xpos>1) //motx carriage return { xpos--; switch (xpos%4) //move printhead { case 0: MX1 break; case 1: MX2 break; case 2: MX3 break; case 3: MX4 break; } _delay_ms(4); } PORTD=0b00000000; _delay_ms(100); //motx off } ///////////////////////////////////////////////// PORTC=0b00000001; _delay_ms(5); PORTC=0b00001001; _delay_ms(5); PORTC=0b00001000; _delay_ms(5); PORTC=0b00001010; _delay_ms(5); PORTC=0b00000010; _delay_ms(5); PORTC=0b00000110; _delay_ms(5); PORTC=0b00000100; _delay_ms(5); PORTC=0b00000101; _delay_ms(5); } PORTC=0b00000001; _delay_ms(50); PORTC=0b00000000; _delay_ms(1); //moty off MCUCR=0b00000111; //The rising edge of INT0 & INT1 generates an interrupt request GICR=0b10000000; //hardware interrupt INT1 (new image) enable sei(); //switch on global interrupts while(1) { if (new_sample_flag){ //new sample arrived new_sample_flag=0; //reset flag scan[video_line]=sample+3; GICR=0b01000000; //enable interrupt int0 (new line) } if (new_frame_flag){ //complete column is sampled PORTC= 0b00010000; //button c4 if (PINC & ( 1 << 4 )) { //paper feed button pushed for (uint8_t i=0;i< 56;i++){ //motx right PORTD=0b10100000; _delay_ms(4); PORTD=0b01100000; _delay_ms(4); PORTD=0b01010010; _delay_ms(4); PORTD=0b10010000; _delay_ms(4); } PORTD=0b00000000; _delay_ms(100);//motx off while((PINC & ( 1 << 4 ))){//paper out y PORTC=0b00010001; _delay_ms(5); PORTC=0b00011001; _delay_ms(5); PORTC=0b00011000; _delay_ms(5); PORTC=0b00011010; _delay_ms(5); PORTC=0b00010010; _delay_ms(5); PORTC=0b00010110; _delay_ms(5); PORTC=0b00010100; _delay_ms(5); PORTC=0b00010101; _delay_ms(5); } PORTC=0b00000001; _delay_ms(50); PORTC=0b00000000; _delay_ms(1); //moty off for (uint8_t i=0;i< 56;i++){ //motx left to origin PORTD=0b10010000; _delay_ms(4); PORTD=0b01010000; _delay_ms(4); PORTD=0b01100000; _delay_ms(4); PORTD=0b10100000; _delay_ms(4); } PORTD=0b00000000; _delay_ms(100);//motx off } new_frame_flag=0; //reset flag sync_count++; if (sync_count==60){ sync_count=0; if (video_column<6) //whole image sampled? { video_column=121; //reset sample column shift } //printer line feed for (uint8_t i=0;i<4;i++){ //paper out y PORTC=0b00000001; _delay_ms(5); PORTC=0b00001001; _delay_ms(5); PORTC=0b00001000; _delay_ms(5); PORTC=0b00001010; _delay_ms(5); PORTC=0b00000010; _delay_ms(5); PORTC=0b00000110; _delay_ms(5); PORTC=0b00000100; _delay_ms(5); PORTC=0b00000101; _delay_ms(5); } PORTC=0b00000001; _delay_ms(50); PORTC=0b00000000; _delay_ms(1); //moty off if (video_column==121){ //printer form feed for (uint8_t i=0;i<70;i++){ //paper out y ///////////////////////////////////////////////// if (i==36){ PORTC=0b00000000; _delay_ms(1);//moty off for (uint16_t i=5;i<227;i++) //dotted line { xpos++; switch (xpos%4) //move printhead { case 0: MX1 break; case 1: MX2 break; case 2: MX3 break; case 3: MX4 break; } if ((i%9)>3) PORTB= 0b00000010; //1 pixel on _delay_ms(3); PORTB= 0b00000000; //0 pixel on _delay_ms(1); if (!(i%9))i++; //kick out some loops to match scanned image on paper } PORTB= 0b00000000; //all pixel off while (xpos>1) //motx carriage return { xpos--; switch (xpos%4) //move printhead { case 0: MX1 break; case 1: MX2 break; case 2: MX3 break; case 3: MX4 break; } _delay_ms(4); } PORTD=0b00000000; _delay_ms(100); //motx off } ///////////////////////////////////////////////// PORTC=0b00000001; _delay_ms(5); PORTC=0b00001001; _delay_ms(5); PORTC=0b00001000; _delay_ms(5); PORTC=0b00001010; _delay_ms(5); PORTC=0b00000010; _delay_ms(5); PORTC=0b00000110; _delay_ms(5); PORTC=0b00000100; _delay_ms(5); PORTC=0b00000101; _delay_ms(5); } PORTC=0b00000001; _delay_ms(50); PORTC=0b00000000; _delay_ms(1); //moty off } xpos=0; for (uint16_t i=5;i<227;i++) //cycle through sample array, plot pixels { xpos++; switch (xpos%4) //move printhead { case 0: MX1 break; case 1: MX2 break; case 2: MX3 break; case 3: MX4 break; } //signal processing, level shift and halftone dithering if (scan[i]>200)scan[i]=200; n_sample=scan[i]; if (n_sample-3>p2_sample){n_sample+=8;} if (n_sample+34)scan[i]=4; if(i<7 ||i>224)scan[i]=0; if (video_column==119){PORTB= 0b00000100;} if (video_column<8){ switch (scan[i]) { case 0: PORTB= 0b00001010; //4 pixel on break; case 1: PORTB= 0b00000010; //3 pixel on break; case 2: PORTB= 0b00000010; //2 pixel on break; case 3: PORTB= 0b00000010; //1 pixel on break; case 4: PORTB= 0b00000010; //0 pixel on break; } } if (video_column<119&&video_column>7){ switch (scan[i]) { case 0: PORTB= 0b00011110; //4 pixel on break; case 1: PORTB= 0b00010110; //3 pixel on break; case 2: PORTB= 0b00000110; //2 pixel on break; case 3: PORTB= 0b00000100; //1 pixel on break; case 4: PORTB= 0b00000000; //0 pixel on break; } } _delay_ms(3); PORTB= 0b00000000; //0 pixel on _delay_ms(1); if (!(i%9))i++; //kick out some loops to match scanned image on paper } PORTB= 0b00000000; //all pixel off while (xpos>1) //motx carriage return { xpos--; switch (xpos%4) //move printhead { case 0: MX1 break; case 1: MX2 break; case 2: MX3 break; case 3: MX4 break; } _delay_ms(4); } PORTD=0b00000000; _delay_ms(100); //motx off video_column-=2; //shift sample column further right } GICR=0b10000000; //enable interrupt int1 (new image), //disable interrupt int0 (new line) } } } ISR(INT1_vect) // interrupt routine - new video image { video_line=277; //reset line index GICR=0b01000000; //enable interrupt int0 (new line), //disable interrupt int1 (new image) } ISR(INT0_vect) // interrupt routine - new video line { GICR=0b00000000; //disable hardware interrupts uint8_t wait=video_column; for (uint8_t i=0;i