Finalproc.c
#pragma regalloc- //I allocate the registers myself #pragma optsize- //optimize for speed #include#include // sprintf #include // delay_ms #include #include #include #include #include #define delayForw 15 #define delayBackw 15 #define delaySample 1 #define dend 20 // distance to end of pattern, for slowing down unsigned char Ain, t; //raw A to D number float voltage; //scaled input voltage int xmax=128, ymax=100; // max distance on x,y axes (match tv screen size) int zig=1; // zig zag flag int userReset=0; // reset flag unsigned char tvFlag=0, tvState=0; int halfstep=0; // motor half-stepping flag int delayTemp; extern unsigned char x_cycle, y_cycle; //position of the stepper motor (4 possibilities) char key, ikey; // key used to hold any button value; ikey to hold just scan mode button unsigned char thres=0; unsigned char white, black, nogo; char go; unsigned char samp1, samp2, samp3; int x, y; // loop variables //-----------video---------------- //cycles = 63.625 * 16 Note NTSC is 63.55 //but this line duration makes each frame exactly 1/60 sec //which is nice for keeping a realtime clock #pragma regalloc+ extern char screen[1600]; char syncON, syncOFF; extern int LineCount; //----------functions-------------- void initialize(void); void scanReset(); void checkTVpush(); void stop(); void sample(); void tv(); void tvclear(); //--------------------------------- void main(void) { initialize(); while(1) { scanReset(); // reset scanner tvclear(); // clear tv halfstep=0; // initialize halfstep option // wait for the user to select a mode to start while (ikey!=0xdc && ikey!=0xec && ikey!=0xf4 && ikey != 0xbc) ikey=PINC & 0xfc; // if halfstep button pushed if (ikey == 0xbc){ if (halfstep){ // half step -> full step PORTA.7 = 1; // turn off led halfstep=0; } else{ // full step -> half step PORTA.7 = 0; // turn on led halfstep=1; } } // wait for the user to select a mode to start while (ikey!=0xdc && ikey!=0xec && ikey!=0xf4 ) ikey=PINC & 0xfc; // calibration: setting threshold value ADCSRA = 0b11000110; delay_ms(delaySample); white = ADCH; for(x=0; x< 25; x++) x_forw(delayForw); delay_ms(3); ADCSRA = 0b11000110; delay_ms(delaySample); black = ADCH; delay_ms(100); thres = ((white - black) / 2) + black; // after calibration, set scanner to an initial position for(y=0; y< 20; y++) { y_forw(delayForw); delay_ms(20); } for(x=0; x< 50; x++) { x_backw(delayBackw); key = PINC & 0x01; if (key == 0 && x > 0) break; } delay_ms(200); /**** SCAN PROCESS ****/ if (ikey == 0xdc) // (key 1) one direction mode: scan one way only (no zig zag) { // step y, scan x for (y=0; y =-50; x--){ // slow down if near edges if (x>dend) delayTemp=delayBackw; else delayTemp=delayBackw*2; if (halfstep) x_backw_half(delayTemp); else x_backw(delayTemp); // detect if user resets key = PINC & 0xfc; if (key == 0xf8){ userReset=1; break; } // detect if button pushed to display image to tv checkTVpush(); if (tvFlag) tv(); // if edge sensor is reached, stop moving backwards key = PINC & 0x01; if (key == 0) break; } if (userReset) break; if (halfstep) y_forw_half(delayForw); else y_forw(delayForw); } } else if (ikey == 0xec)// (key 2) zig zag mode: scanner slows at ends to try { // to avoid shaking, also with software compensation zig=1; // initialize zig flag // step y, scan x. zigzag pattern. for (y=0; y =-50; x--){ sample(); if (x>=0) video_pt(x, y, Ain); // when x rod is nearing end, slow down if (x>dend) delayTemp=delayBackw; else delayTemp=delayBackw*2; if (halfstep) x_backw_half(delayTemp); else x_backw(delayTemp); // detect if user resets key = PINC & 0xfc; if (key == 0xf8){ userReset=1; break; } // detect if button pushed to display image to tv checkTVpush(); if (tvFlag) tv(); // if reset sensor is reached, stop moving backwards key = PINC & 0x01; if (key == 0) { // fill in the rest of the screen line while (x>=0){ video_pt(x,y, Ain); x--; } break; } } } if (userReset) break; zig=!zig; // slow down scanner when it's about to change directions delay_ms(20); if (halfstep) y_forw_half(delayForw); else y_forw(delayForw); } } else if (ikey == 0xf4)// (key3) normal zig zag mode with software compensation { zig=1; // initialize zig flag // step y, scan x. zigzag pattern. for (y=0; y =-50; x--){ sample(); if (x>=0) video_pt(x, y, Ain); if (halfstep) x_backw_half(delayBackw); else x_backw(delayBackw); // detect if user resets key = PINC & 0xfc; if (key == 0xf8){ userReset=1; break; } // detect if button pushed to display image to tv checkTVpush(); if (tvFlag) tv(); // if reset sensor is reached, stop moving backwards key = PINC & 0x01; if (key == 0){ while (x>=0){ video_pt(x,y, Ain); x--; } break; } } } if (userReset) break; zig=!zig; if (halfstep) y_forw_half(delayForw); else y_forw(delayForw); } } // end if/else if/else if /**** END SCAN PROCESS ****/ if (userReset) userReset=!userReset; else { tvFlag=1; tv(); // Display the scanned image to tv screen } } // main program loop } //end of main void initialize(void) { //init the A to D converter //channel zero/ left adj /int Aref //Connected to internal 2,56V use 7..6 bits as 00 for Vref ADMUX = 0b00100000; //enable ADC and set prescaler to 1/64*8MHz=125,000 //and set int enable ADCSRA = 0b10000110; // set ports DDRD=0xff; // PORT D is output: pins 5, 6 to tv, pin 7 to half-step LED PORTD=0x00; DDRC=0x00; // PORT C is input: reads the x and y reset sensors PORTC=0xfc; // Turn pullups on pins 0, 1 for sensors, rest pulldown for buttons DDRB=0xff; // PORT B is output: controls the motors PORTB=0x00; // upper 4 bits for x motor, lower for y motor DDRA=0x80; // PORTA bit0 is adc and bit7 is output for led PORTA.7 = 1; // initialize variables x_cycle = 0; y_cycle = 0; key = 0x00; ikey = 0x00; tvFlag=0; tvState=0; halfstep=0; LineCount = 1; syncON = 0b00000000; syncOFF = 0b00100000; MCUCR = 0b10000000; #asm sei #endasm } // reset the scanner to initial corner position void scanReset() { key = PINC & 0x03; // brink x back until sensor hit while(key == 0x01 || key == 0x03){ x_backw(delayBackw); key = PINC & 0x03; } key = PINC & 0x03; // bring y back until sensor hit while(key == 0x02 || key == 0x03){ y_backw(delayBackw); key = PINC & 0x03; } ikey = 0x00; // reset the scan mode } // tv display toggle and debounce void checkTVpush() { key=PINC & 0xf0; // no-button-push state if (key==0xf0) tvState=0; // enter button-pushed state, toggle flag for tv/no tv if (key == 0x70 && !tvFlag && tvState==0) { tvState=1; tvFlag=1; } else if (key==0x70 && tvFlag && tvState==0) { tvState=1; tvFlag=0; } } // sample with the photo sensor through the ADC void sample(){ // take 3 samples, if 2 are black, final sample will be black ADCSRA = 0b11000110; delay_ms(delaySample); samp1 = ADCH; if (samp1 > thres) samp1 = 1; else samp1 = 0; ADCSRA = 0b11000110; delay_ms(delaySample); samp2 = ADCH; if (samp2 > thres) samp2 = 1; else samp2 = 0; ADCSRA = 0b11000110; delay_ms(delaySample); samp3 = ADCH; if (samp2 > thres) samp3 = 1; else samp3 = 0; Ain = samp1 + samp2 *2 + samp3*4; if (Ain == 0 || Ain == 1 || Ain == 2 || Ain == 4) Ain = 0; else Ain = 1; } // display scanned image to tv void tv(){ DDRD=0xff; // Redefine PortD upper half output for TV PORTD=0x00; //Lower half is pullup inputs for push buttons //init timer 1 to generate sync OCR1A = lineTime; //One NTSC line TCCR1B = 9; //full speed; clear-on-match TCCR1A = 0x00; //turn off pwm and oc lines TIMSK = 0x10; //enable interrupt T1 cmp go = 1; while(go) { //stall here until next line starts //sleep enable; mode=idle //use sleep to make entry into sync ISR uniform time #asm ("sleep"); //The following code executes during the vertical blanking //Code here can be as long as //a total of 60 lines x 63.5 uSec/line x 8 cycles/uSec if (LineCount==231) { // exit tv on button push checkTVpush(); if (!tvFlag) go=0; } //line 231 } //while TIMSK = 0x00; //disable interrupt } // clear the tv screen buffer void tvclear() { int a, b; for (a=0; a<=99; a++) { for (b=0; b<=127; b++) video_pt(b, a, 0); } }