void setup(void) { wdt_reset(); wdtDisable(); setPinsOutput(); randomMode = btn.read(); //invoke random wake mode if button pressed while (btn.isPressed()) btn.read(); //wait for the button to be released msRunTime = randomMode ? RANDOM_RUN_MS : MANUAL_RUN_MS; wdtLimit = random(RANDOM_SLEEP_MIN, RANDOM_SLEEP_MAX + 1); }
void goToSleep(void) { do { GIMSK |= _BV(INT0); //enable INT0 MCUCR &= ~(_BV(ISC01) | _BV(ISC00)); //INT0 on low level ACSR |= _BV(ACD); //disable the analog comparator ADCSRA &= ~_BV(ADEN); //disable ADC set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); if (randomMode) wdtEnable(); //start the WDT if we're in random mode //turn off the brown-out detector. //must have an ATtiny45 or ATtiny85 rev C or later for software to be able to disable the BOD. //current while sleeping will be <0.5uA if BOD is disabled, <25uA if not. cli(); mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector mcucr2 = mcucr1 & ~_BV(BODSE); MCUCR = mcucr1; MCUCR = mcucr2; sei(); //ensure interrupts enabled so we can wake up again sleep_cpu(); //go to sleep //----zzzz----zzzz----zzzz----zzzz cli(); //wake up here, disable interrupts GIMSK = 0x00; //disable INT0 sleep_disable(); wdtDisable(); //don't need the watchdog while we're awake sei(); //enable interrupts again (but INT0 is disabled above) if (buttonWake) { //what woke us keepSleeping = false; //the button woke us, so turn the lights on again msRunTime = MANUAL_RUN_MS; btn.read(); while (!btn.wasReleased()) btn.read(); //wait for the button to be released } else if (randomMode && (++wdtCount < wdtLimit)) { keepSleeping = true; //setPinsOutput(); //briefly blink an LED so we can see the wdt wake-ups //digitalWrite(LED4, HIGH); //_delay_ms(10); //setPinsInput(); } else { keepSleeping = false; msRunTime = RANDOM_RUN_MS; if (++mode > MAX_MODE) mode = 0; } } while (keepSleeping); setPinsOutput(); buttonWake = false; msWakeUp = millis(); if (randomMode) { //set up for next time wdtCount = 0; wdtLimit = random(RANDOM_SLEEP_MIN, RANDOM_SLEEP_MAX + 1); } }
void main(void) { static uint32_t dataPointer = 0; static uint32_t readPointer = 0; static uint32_t dataAddress; static uint32_t dataLength; static uint16_t bufPointer = 0; uint8_t c = 0; uint8_t uart = 0; wdtDisable(); // Move Interrupt Vectors into Bootloader Section c = INTERRUPTMOVE; INTERRUPTMOVE = c | (1 << IVCE); INTERRUPTMOVE = c | (1 << IVSEL); TCRA |= (1 << WGM21); // CTC Mode #if F_CPU == 16000000 TCRB |= (1 << CS22); // Prescaler: 64 OCR = 250; #else #error F_CPU not compatible with timer module. DIY! #endif TIMS |= (1 << OCIE); // Enable compare match interrupt for (uint8_t i = 0; i < serialAvailable(); i++) { serialInit(i, BAUD(BAUDRATE, F_CPU)); } sei(); set(buf, 0xFF, sizeof(buf)); debugPrint("YASAB "); debugPrint(VERSION); debugPrint(" by xythobuz\n"); while (systemTime < BOOTDELAY) { for (uint8_t i = 0; i < serialAvailable(); i++) { if (serialHasChar(i)) { c = serialGet(i); // Clear rx buffer uart = i; goto ok; // Yeah, shame on me... } } } gotoApplication(); ok: serialWrite(uart, OKAY); while (!serialTxBufferEmpty(uart)); // Wait till it's sent uint32_t t = systemTime; while (systemTime < (t + BOOTDELAY)) { if (serialHasChar(uart)) { if (serialGet(uart) == CONFIRM) { goto ack; // I deserve it... } } } gotoApplication(); ack: serialWrite(uart, ACK); while (!serialTxBufferEmpty(uart)); dataAddress = readFourBytes(uart, serialGetBlocking(uart)); serialWrite(uart, OKAY); while (!serialTxBufferEmpty(uart)); // Wait till it's sent debugPrint("Got address!\n"); dataLength = readFourBytes(uart, serialGetBlocking(uart)); if ((dataAddress + dataLength) >= BOOTSTART) { serialWrite(uart, ERROR); } else { serialWrite(uart, OKAY); } while (!serialTxBufferEmpty(uart)); debugPrint("Got length!\n"); while (readPointer < dataLength) { buf[bufPointer] = serialGetBlocking(uart); readPointer++; if (bufPointer < (SPM_PAGESIZE - 1)) { bufPointer++; } else { bufPointer = 0; program(uart, dataPointer + dataAddress, buf); dataPointer += SPM_PAGESIZE; set(buf, 0xFF, sizeof(buf)); serialWrite(uart, OKAY); } } debugPrint("Got data!\n"); if (bufPointer != 0) { program(uart, dataPointer + dataAddress, buf); serialWrite(uart, OKAY); } uint8_t sreg = SREG; cli(); boot_spm_busy_wait(); boot_rww_enable(); // Allows us to jump to application SREG = sreg; gotoApplication(); }