//------------------------------------------------------------------------------ int __attribute__((OS_main)) main(void) { dnaUsbInit(); enableLed(); usbCommand = ceCommandIdle; usbRNAPacketExpected = 1; TCCR0B = 1<<CS01 | 1<<CS00; // set 8-bit timer prescaler to div/64 TIMSK0 = 1<<TOIE0; // enable the interrupt rnaInit(); sei(); setLedOff(); for(;;) { rnaPoll(); if ( rnaPacketAvail ) { setLedOn(); rnaPacketAvail = 0; _delay_ms( 50 ); while ( !rnaSend(usbRNATo, usbRNAPacket, usbRNAPacketExpected) ) { _delay_ms(1); } setLedOff(); } /* if ( usbRNAPacketPos == usbRNAPacketExpected ) { usbRNAPacketPos = 0; if ( *usbRNAPacket == RNATypeDebugString ) { usbRNAPacket[usbRNAPacketExpected] = 0; usbprint( (char *)usbRNAPacket + 1, usbRNAPacketExpected ); } } */ } }
//------------------------------------------------------------------------------ int __attribute__((OS_main)) main(void) { setupA(); setupB(); setupVariables(); dnaUsbInit(); INSTALL_MORLOCK_DEFAULTS; saveEEPROMConstants(); loadEEPROMConstants(); // 12000000 / (64 * 94) = 1994.680 interrupts per second // accomplished by using timer0 in waveform generation mode 2 TCCR0B = 1<<CS01 | 1<<CS00; // set 8-bit timer prescaler to div/64 OCR0A = 94; TCCR0A = 1<<WGM01; TIMSK0 = 1<<OCIE0A; // mode 2, reset counter when it reaches OCROA TCCR1B = 1<<WGM12 | 1<<CS12;// CTC for OCR1A, clock select // set up A2D ADMUX = 1<<MUX0; // A1, Vcc ref ADCSRA = 1<<ADEN | 1<<ADPS2; // enable A2D, x16 DIDR0 = ADC1D; // disable all digital function on A1 ADCSRB = 1<<ADLAR; // knock off lower two bits, implementation is not that accurate PRR = 1<<PRUSI; // not using USI (yet) rnaInit(); sei(); _delay_ms(2); // let state settle, and make sure housekeeping ISR runs if( !triggerState && !consts.locked ) { timesToBlinkLight = 1; inProgramMode = true; } for(;;) { PRR |= 1<<PRTIM1; // power down timer, don't waste power // spin until a fire condition is triggered from the ISR while( !startFireCycle ) { sampleEye = false; if ( rnaRequestsConfigData ) { usbRNAPacket[0] = RNATypeSetConfigData; for( unsigned char c=0; c<sizeof(consts); c++ ) { usbRNAPacket[c+1] = ((unsigned char *)&consts)[c]; } rnaSend( rnaRequestsConfigData, usbRNAPacket, sizeof(consts) + 1 ); rnaRequestsConfigData = 0; } if ( !millisecondCountBox && consts.eyeEnabled ) { millisecondCountBox--; digitizeEye(); isLedOn = eyeBlocked ? true : false; } if ( eepromConstantsDirty ) { isLedOn = true; setLedOn(); eepromConstantsDirty = false; saveEEPROMConstants(); isLedOn = false; } if ( rnaPacketAvail ) { isLedOn = true; setLedOn(); rnaPacketAvail = false; _delay_ms( 50 ); rnaSend( usbRNATo, usbRNAPacket, usbRNAPacketExpected ); isLedOn = false; } } sampleEye = true; // set up the timer PRR &= ~(1<<PRTIM1); // timer back on TCNT1 = 0; // reset the timer TIFR1 |= 1<<OCF1A; // reset compare match if ( shotsInString < consts.rampEnableCount ) { shotsInString++; } // setup complete, cycle the marker if ( consts.singleSolenoid ) { cycleSingleSolenoid(); } else { cycleDoubleSolenoid(); } // bursting? if so count it down if ( burstCount && --burstCount ) { startFireCycle = true; } else if ( currentFireMode != ceFullAuto ) { startFireCycle = false; } isLedOn = false; // make sure at least this much time elapses at the end of a fire cycle millisecondCountBox = consts.shortCyclePreventionInterval; while( millisecondCountBox ); while( !(TIFR1 & 1<<OCF1A) ); // wait for end of fire cycle if ( currentFireMode == ceRamp && startFireCycle && (consts.rampTopMode != ceSemi) ) // officially hit top rate, blow guts out { // a shot was scheduled at the maximum rate it could be, go // ahead and shift up to whatever top mode the user wanted currentFireMode = consts.rampTopMode; scheduleShotBox = 0; scheduleShotRate = 0; } } }
//------------------------------------------------------------------------------ int __attribute__((OS_main)) main() { // B0 top button (1) // B1 bottom button (3) // B2 RNA int0 // B3 middle button // B4 power toggle DDRB = 0b00010000; // one output, the power toggle, everything else is an input PORTB = 0b00011011; // initial state: turn on pullups and keep the power on! rnaInit(); // interrupt driven, if we have the space it's the most convenient // configure the a2d to sample the middle button, which reads // nearly 1.1v for 'pressed' and about .8v for "not pressed" as a // result of the power-control circuitry design ADMUX = 1<<REFS1 | 1<<MUX0 | 1<<MUX1 | 1<<ADLAR; // B3, 1.1v ref, knock off lower two bits ADCSRA = 1<<ADEN; // enable A2D, x16 DIDR0 = 1<<ADC3D; // disable all digital function on B3 sei(); _delay_ms(1); // let values settle a2dStartConversion(); a2dWaitForConversionComplete(); // throw out first reading // unsigned char high = 0xF0; // unsigned char low = 0xD0; /* unsigned char pos = 0; _delay_ms( 500 ); // wait for everyone to boot before probing (the OLED in particular takes a few 100ms) unsigned int deltaTargets[0xE]; // when a button is pressed, everyone gets a notice for( unsigned char probe=1; probe<0x10; probe++ ) { if ( rnaProbe(probe) ) { deltaTargets[pos++] = probe; } } deltaTargets[pos] = 0; */ unsigned char oldStatus = 0; unsigned char status; unsigned char rnaPacket[3]; rnaPacket[0] = RNATypeButtonStatus; rnaPacket[1] = 0; unsigned int cyclesOn = 0; unsigned int doubleClickStateCountdown[3] = { 0, 0, 0 }; unsigned char doubleClickStateSent[3] = { 1, 1, 1 }; unsigned char generateRelease = 0; for(;;) { if ( generateRelease ) { generateRelease = 0; _delay_ms( 20 ); rnaPacket[1] = 0; rnaSend( RNADeviceOLED, rnaPacket, 2 ); _delay_ms( 20 ); } status = 0; a2dStartConversion(); a2dWaitForConversionComplete(); // did we find a calibration? if ( ADCH < 0xE0 ) { cyclesOn = 0; // power button not pressed, reset 'power off' logic and set state status |= ButtonBitMiddle; } if ( PINB & 0x1 ) { status |= ButtonBitBottom; } if ( PINB & 0x2 ) { status |= ButtonBitTop; } // the buttons are 'active low' but keep things // straightforward with a '1' meaning the button has been // pressed status ^= 0x7; for( unsigned char c = 0; c<3; c++ ) { if( (status & (1<<c)) && !(oldStatus & (1<<c)) ) { // just pressed if ( c == 1 ) { if ( doubleClickStateCountdown[c] ) // and it's a double-click { doubleClickStateSent[c] = 1; rnaPacket[1] = (1<<c) | ButtonBitDouble; generateRelease = 1; } doubleClickStateCountdown[c] = 0; } else { rnaPacket[1] = (1<<c); } } else if ( !(status & (1<<c)) && (oldStatus & (1<<c)) ) { // just released if ( c == 1 ) { if ( doubleClickStateSent[c] ) { doubleClickStateSent[c] = 0; } else { doubleClickStateCountdown[c] = DOUBLE_CLICK_INTERVAL; } } else { generateRelease = 1; } } else if ( doubleClickStateCountdown[c] ) { if ( !--doubleClickStateCountdown[c] ) { rnaPacket[1] = (1<<c); generateRelease = 1; } } // event generated? send it if ( rnaPacket[1] && rnaSend(RNADeviceOLED, rnaPacket, 2) == -1 ) { _delay_ms(2); rnaSend( RNADeviceOLED, rnaPacket, 2 ); } rnaPacket[1] = 0; } if ( oldStatus != status ) // debounce transitions { // rnaPacket[1] = status; // rnaSend( RNADeviceOLED, rnaPacket, 2 ); oldStatus = status; _delay_ms( 20 ); } else { _delay_ms( 1 ); } if ( cyclesOn++ > POWER_OFF_INTERVAL ) { rnaPacket[1] = ButtonBitPowerOff; rnaSend( RNADeviceOLED, rnaPacket, 2 ); PORTB &= 0b11101111; // turn off the power pin (power won't actually die until the power button is released) for(;;); } } }