/*================================== * Positracker code. *=================================*/ //----------------------------------------------------------------------------- // Includes //----------------------------------------------------------------------------- #include "c8051f320.h" // SFR declarations #include "USB_MAIN.h" #include "USB_DESCRIPTOR.h" #include "USB_REGISTER.h" #include "sample.h" #include "intrins.h" //----------------------------------------------------------------------------- // Global CONSTANTS //----------------------------------------------------------------------------- sbit SW1 = P2^0; // SW2='0' means switch pressed sbit SW2 = P2^1; // SW2='0' means switch pressed sbit LED1 = P2^2; // LED='1' means ON sbit LED2 = P2^3; // LED='1' means ON sbit IN1 = P1^0; sbit IN2 = P1^1; sbit IN3 = P1^2; sbit IN4 = P1^3; //----------------------------------------------------------------------------- // Function PROTOTYPES //----------------------------------------------------------------------------- void init(void); xdata unsigned char smpl[1024] _at_ 0; BYTE Out_Packet[8]; // Last packet received from host BYTE In_Packet[8]; // Next packet to sent to host //----------------------------------------------------------------------------- // MAIN Routine //----------------------------------------------------------------------------- unsigned char adj( char tempc, char vel ) { if( tempc>(30+vel) ) tempc-=60; if( tempc<(vel-30) ) tempc+=60; return tempc; } void pause( unsigned char val ) { unsigned char cnt; for( ; val!=0; val-- ) for( cnt=255; cnt!=0; cnt-- ); } void main (void) { unsigned short position; unsigned short recordOffset; unsigned short position1; unsigned short position2; unsigned short position3; char os1, os2, os3, pos1, pos2, pos3; char vel1,vel2,vel3; // disable watchdog timer PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer enable) init(); for(;;) { // Retrieve starting position. // Doesn't matter that this is semi-inaccurate // need to do some sort of variance testing to make sure // 1 invalid value doesn't ruin everything pause(255); // could prob do some sort of subdivision thing here to speed things up for( recordOffset=0; recordOffset<32768; recordOffset+=256 ) { // sample at recordOffset EIE1 &= ~0x02; sample(-recordOffset,3); EIE1 |= 0x02; // re-enable usb // pause before next wave pause(255); // make sure the first 256(128) positions have something in them if( sum(0,128)>16 ) break; } // find individual position offsets position1 = exceeds(8,1); // both *2 as 2 samples per memory pos position2 = exceeds(8,2); position3 = exceeds(8,3); // analyse phase and adjust all positions to coincide phase(); vel1 = 0;vel2 = 0;vel3 = 0; os1 = smpl[1021]; os2 = smpl[1022]; os3 = smpl[1023]; while (1) { // find minimum positionValue position = position1; if( position2 6Mhz // sample clock runs at sysclock / 10 -> 2400Khz ~ 1200Khz per 2 samples // ratio is 5 timer clocks per 2 samples clocks // NOT: best fit is 5 timer clocks per 2 sample clocks // so if 128 sample clocks under shift by 32 sample clocks // which is 80 timer clocks // check if within lower range bounds if( position < 64 ) { // dec value position1 += 60; position2 += 60; position3 += 60; recordOffset -= 150; } // check if within upper range bounds if( position > 200 ) { // inc value position1 -= 120; position2 -= 120; position3 -= 120; recordOffset += 300; } // sample EIE1 &= ~0x02; // have to disable usb interrupt here to prevent it interrupting sampling /*recordOffset = */sample( -recordOffset, 3 ); EIE1 |= 0x02; // re-enable usb // missing signal, ping for new position if( position1>1800 || position2>1800 || position3>1800 || sum(0,640)<32) break; // TODO: check quality of signal // if failed break outta this loop and re-ping for locations phase(); // adjust positions based on phase results // old phases are os# new phases are pos# // so assuming for now a stationary target // move closer is abs(pos-os) ... yadda yadda // find min difference between phases pos1 = smpl[1021]; vel1 = adj(pos1-os1,vel1); os1 = pos1; position1 += vel1; pos2 = smpl[1022]; vel2 = adj(pos2-os2,vel2); os2 = pos2; position2 += vel2; pos3 = smpl[1023]; vel3 = adj(pos3-os3,vel3); os3 = pos3; position3 += vel3; // write back to usb EIE1 &= ~0x02; *((unsigned short*)In_Packet) = recordOffset; *((unsigned short*)(In_Packet+2)) = position1; *((unsigned short*)(In_Packet+4)) = position2; *((unsigned short*)(In_Packet+6)) = position3; EIE1 |= 0x02; // re-enable usb } } } //------------------------- // Delay //------------------------- // Used for a small pause, approximately 80 us in Full Speed, // and 1 ms when clock is configured for Low Speed // /*void delay( unsigned short time ) { time =- time; TCON = 0x00; // stop timer TL0 = time&0xFF; // set timer TH0 = time/256; TF0 = 0; // reset interrupt bit TCON = 0x10; for(;TF0==0;); TCON = 0x00; }*/ //----------------------------------------------------------------------------- // sysclockInit //----------------------------------------------------------------------------- // // This routine initializes the system clock to use the internal 24.5MHz / 8 // oscillator as its clock source. Also enables missing clock detector reset. // void init(void) { // sysclockInit #ifdef _USB_LOW_SPEED_ OSCICN |= 0x03; // Configure internal oscillator for // its maximum frequency and enable // missing clock detector CLKSEL = SYS_INT_OSC; // Select System clock CLKSEL |= USB_INT_OSC_DIV_4; // Select USB clock #else unsigned char n; // initialize clock sources OSCICN |= 0x03; // Configure internal oscillator for its maximum frequency CLKMUL = 0x00; // Select internal oscillator as input to clock multiplier CLKMUL |= 0x80; // Enable clock multiplier CLKMUL |= 0xC0; // Initialize the clock multiplier for(n=255;n!=0;n--); while(!CLKMUL & 0x20); // Wait for multiplier to lock CLKSEL = SYS_4X_DIV_2; // Select system clock CLKSEL |= USB_4X_CLOCK; // Select USB clock #endif /* _USB_LOW_SPEED_ */ // usb0Init POLL_WRITE_BYTE(POWER, 0x08); // Force Asynchronous USB Reset POLL_WRITE_BYTE(IN1IE, 0x07); // Enable Endpoint 0-2 in interrupts POLL_WRITE_BYTE(OUT1IE, 0x07); // Enable Endpoint 0-2 out interrupts POLL_WRITE_BYTE(CMIE, 0x07); // Enable Reset, Resume, and Suspend interrupts #ifdef _USB_LOW_SPEED_ USB0XCN = 0xC0; // Enable transceiver; select low speed POLL_WRITE_BYTE(CLKREC, 0xA0); // Enable clock recovery; single-step mode // disabled; low speed mode enabled #else USB0XCN = 0xE0; // Enable transceiver; select full speed POLL_WRITE_BYTE(CLKREC, 0x80); // Enable clock recovery, single-step mode // disabled #endif /* _USB_LOW_SPEED_ */ EIE1 |= 0x02; // Enable USB0 Interrupts EA = 1; // Global Interrupt enable // Enable USB0 by clearing the USB Inhibit bit POLL_WRITE_BYTE(POWER, 0x01); // and enable suspend detection // portInit XBR0 = 0x00; // no digital peripherals selected XBR1 = 0x40; // Enable crossbar and weak pull-ups P0MDOUT = 0x0f; // P0.0, P0.1 push/pull P0MDIN = 0x0f; // P0.0, P0.1 digital // init leds / switchs P2MDIN = 0x0F; // all digital input P2MDOUT = 0x0C; // switchs open drain / leds push pull P2SKIP = 0x00; // skip nothing P1MDIN = 0x07; // all digital input P1MDOUT = 0x00; // switchs open drain P1SKIP = 0x00; // skip nothing // timerInit // config T0 CKCON = 0x01; // start T0, T0 runs off sysclock/4, should give us ~6m range TL0 = 0x00; // Timer 0 Low Byte TH0 = 0x00; // Timer 0 High Byte TMOD = 0x01; // Timer Mode Register TCON = 0x00; // Timer Control Register stop } //#define ULTRA_GROUND P0 = P0&~3 //#define ULTRA_INIT P0 = (P0&~3)|1 //#define ULTRA_TOGGLE P0 = P0^3 /** void testTone(void) { char pulseLength; char pause; ULTRA_INIT; for( pulseLength=255; pulseLength!=0; pulseLength-- ) { // toggle ultrasonic outputs ULTRA_TOGGLE; for( pause=48; pause!=0; pause-- ); } ULTRA_GROUND; } */