void loop() { // display information about the counter Serial.print("Awake for "); Serial.print(count); Serial.println("sec"); count++; delay(1000); // waits for a second // compute the serial input if (Serial.available()) { int val = Serial.read(); if (val == 'S') { Serial.println("Serial: Entering Sleep mode"); delay(100); // this delay is needed, the sleep //function will provoke a Serial error otherwise!! count = 0; sleepNow(); // sleep function called here } if (val == 'A') { Serial.println("Hola Caracola"); // classic dummy message } } // check if it should go to sleep because of time if (count >= 10) { Serial.println("Timer: Entering Sleep mode"); delay(100); // this delay is needed, the sleep //function will provoke a Serial error otherwise!! count = 0; sleepNow(); // sleep function called here } }
// put the rfbee into sleep int setSleepMode() { #ifdef DEBUG printf("going to sleep\r\n"); #endif ccx_strobe(CCx_SIDLE); ccx_strobe(CCx_SPWD); sleepNow(SLEEP_MODE_IDLE); //sleepNow(SLEEP_MODE_PWR_DOWN); #ifdef DEBUG printf("just woke up\r\n"); #endif setRFBeeMode(); setSerialDataMode(); return NOTHING; }
bool Pendant::update() { now = millis(); if (buttonPressedAt) { // Cycle modes when held for a long time if (now > (buttonPressedAt + PENDANT_CYCLE_DELAY)) { toggleCycleMode(); } else if (now > (buttonPressedAt + PENDANT_SLEEP_DELAY)) { sleepOnRelease = true; } } // Update pushed button state. updateButtonState(); // Handle button release. if (buttonReleased()) { if (sleepOnRelease) { sleepNow(); } else if (changeModeOnRelease) { mode++; if (cyclingMode) lastCycle = now; } else { changeModeOnRelease = true; } } // Cycle mode if we are cycling, and it's time. if (cyclingMode && (now > (lastCycle + PENDANT_CYCLE_DURATION))) { lastCycle = now; mode++; } // Go black to indicate power off. if (sleepOnRelease) { FastLED.showColor(CRGB::Black); } // Do the animations! // YAY! else { if (mode >= modes) mode = 0; return true; } return false; }
void loop() // run over and over again { unsigned long int time; byte i=0; CCShield out(myClockPin,mySerDataPin,mySerDataPin2, 11); out.setBrightness(255); //out.set(0xffffffff,0xffffffff,0xf); delay(250); if (digitalRead(wakePin)==HIGH) // Still held -- mode select { unsigned long start = millis(); while (digitalRead(wakePin)==HIGH) { unsigned long mode = (millis()-start)/500; mode = mode % NUMMODES; out.set(1UL<<cvt(mode,0),0,0); delay(50); i = mode; } } seed += analogRead(rightDial)+analogRead(leftDial); // Try to get a random starter if (1) { time = analogRead(rightDial); time = time * 4000; if (time < 5000) time = 5000; if (i==0) RandomFader(out,time); else if (i==1) Sequence(out,time); else if (i==2) EtchSketch(out,time); else if (i==3) BrightnessTest(out,time); //out.set(0xffffffff,0xffffffff,0xf); /* ALL ON */ out.set(0,0,0); /* ALL OFF */ delay(500); // Debounce reset button input //attachInterrupt(wakePin-2,sleepInterrupt,RISING); out.set(0,0,0); /* ALL OFF */ sleepNow(); } }
void main() { // power management setup clock_prescale_set(clock_div_16); // 500 kHz clock ADCSRA = 0; // DIE, ADC! DIE!!! power_adc_disable(); power_usi_disable(); power_timer1_disable(); ACSR = _BV(ACD); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // millisecond timer setup TCCR0A = _BV(WGM01); // mode 2 - CTC TCCR0B = _BV(CS01) | _BV(CS00); // prescale = 64 TIMSK0 = _BV(OCIE0A); // OCR0A interrupt only. OCR0A = IRQ_CYCLE_LENGTH + 1; millis_counter = 0; irq_cycle_pos = 0; sei(); // I/O port setup DDRA = _BV(PA0) | _BV(PA1) | _BV(PA2) | _BV(PA3) | _BV(PA7); DDRB = _BV(PB0) | _BV(PB1) | _BV(PB2); PORTA = _BV(PA5); // enable the pull-up on the button pin PORTB = 0; unsigned char pattern = eeprom_read_byte(EE_PATTERN_NUM); if (pattern >= PATTERN_COUNT) pattern = 0; place_in_pattern = -1; milli_of_next_change = 0; button_debounce_time = 0; button_press_time = 0; ignoring_button = 0; while(1) { unsigned long now = millis(); // poll for button events unsigned int event = checkEvent(); switch(event) { case EVENT_LONG_PUSH: sleepNow(); continue; case EVENT_SHORT_PUSH: if (++pattern >= PATTERN_COUNT) pattern = 0; place_in_pattern = -1; milli_of_next_change = 0; eeprom_write_byte(EE_PATTERN_NUM, pattern); continue; } // If it's time to move to the next step in a pattern, pull out its // mask and clear all of the LEDs. // Note that now > milli_of_next_change is wrong here because our // time wraps. now - milli_of_next_change > 0 *looks* the same, // but handles cases where the sign differs. if (milli_of_next_change == 0 || ((long)(now - milli_of_next_change)) >= 0) { // It's time to go to the next step in the pattern place_in_pattern++; const struct pattern_entry *our_pattern = (struct pattern_entry *)pgm_read_ptr(&(patterns[pattern])); struct pattern_entry entry; do { memcpy_P(&entry, (void*)(&(our_pattern[place_in_pattern])), sizeof(struct pattern_entry)); // A duration of 0 is the end of the pattern. if (entry.duration != 0) break; place_in_pattern = 0; } while(1); // This means a pattern of a single entry with 0 duration is kryptonite. current_mask = entry.mask; // Turn out all the lights for(int i = 0; i < LED_COUNT; i++) { *((unsigned char *)pgm_read_ptr(&(LED_PORT[i]))) &= ~_BV(pgm_read_byte(&(LED_PIN[i]))); } milli_of_next_change = now + entry.duration; current_led = 99; //invalid } // Now multiplex the LEDSs. Rotate through all of the set bits in the // current mask and turn the next one on every pass through this loop. if (current_mask != 0) { // if it IS zero, then all the lights are out anyway. unsigned char next_led = current_led; while(1) { // we know it's not zero, so there's at least one bit set if (++next_led >= LED_COUNT) next_led = 0; if (current_mask & (1 << next_led)) break; // found one! } if (next_led != current_led) { // turn the old one off and the new one on. if (current_led < LED_COUNT) // is it safe? *((unsigned char *)pgm_read_ptr(&(LED_PORT[current_led]))) &= ~_BV(pgm_read_byte(&(LED_PIN[current_led]))); *((unsigned char *)pgm_read_ptr(&(LED_PORT[next_led]))) |= _BV(pgm_read_byte(&(LED_PIN[next_led]))); current_led = next_led; } } } }
void Events::waitNext(word sleepMode) { if (queueSize >= MAX_QUEUE_SIZE) { LOG("Queue was full"); queueSize = MAX_QUEUE_SIZE; } bool found = false; unsigned long now = 0, next = 0xffffffffL; // loop on event queue THEN on timers // but at end of event queue, we may have new items in queue => must loop do { // for each fired events, call callback for (int q = 0; q < queueSize; q++) { for (int h = 0; h < eventHandlerMax; h++) { if (eventQueueTypes[q] == handlers[h].type) { // this handler may be for this event eventHandler *hdl = &(handlers[h]); if (hdl->type == event_input) { // is it for this interrupt ? if (hdl->inputSpec.interrupt == eventQueueDetails[q]) { hdl->callback(eventQueueDetails[q], hdl->data); } } else if (hdl->type == event_analogcomp) { bool state = analogCompValue() ? RISING : FALLING; if (hdl->analogCompSpec.mode == CHANGE || hdl->analogCompSpec.mode == state) { hdl->callback(state, hdl->data); } } else if (hdl->type >= 10) { hdl->callback(eventQueueDetails[q], hdl->data); } } } } // if a handler fired an event in queue, loop will continue on it // => here, we can empty it safely queueSize = 0; // look at expired timer events + compute next time // TODO : must avoid to use millis/micros // => must compute our own time elapsed since preceding call, using timer values #ifdef WITHOUT_MILLIS_FUNCTIONS now = myMillis() * 1000; #else now = (millis() * 1000) + (micros() % 1000); #endif next = 0xffffffffL; for (int h = 0; h < eventHandlerMax; h++) { eventHandler *hdl = &(handlers[h]); if (hdl->type == event_timer) { // is it expired ? => handle if (hdl->timerSpec.next <= now + TIMER_EVENT_PRECISION) { hdl->callback(hdl->timerSpec.count - 1, hdl->data); if (hdl->timerSpec.count == 1) { // last timer iteration => remove it unregisterEvent(hdl); hdl->timerSpec.next = 0xffffffffL; } else { if (hdl->timerSpec.count > 0) { // remaining iterations => just update counter hdl->timerSpec.count--; } // infinite iterations, or remaining ones => compute next time do { hdl->timerSpec.next += hdl->timerSpec.delay * 1000; // loop over iterations in case we missed some } while(hdl->timerSpec.next < now + TIMER_EVENT_PRECISION); } } if (next > hdl->timerSpec.next) { next = hdl->timerSpec.next; found = true; } } } // here, timer handler having queued new events must be handled => loop } while (queueSize > 0); if (!found) { if (defaultTimeout == 0) { sleepNow(sleepMode); } else { // wait in a interruptible manner, until default timeout delayIdleWith(defaultTimeout, defaultTimer, sleepMode, true); } } else { // wait in a interruptible manner // TODO : remove time elapsed since "now" calculation, but risks to be too late // round value too TIMER_EVENT_PRECISION multiple long delay = next - now, rem = delay % TIMER_EVENT_PRECISION; if (rem > TIMER_EVENT_PRECISION / 2) { delay -= rem + TIMER_EVENT_PRECISION; } else { delay -= rem; } delayIdleWith(delay, defaultTimer, sleepMode, true); } analogCompAlready = false; eventLoop++; }
int main(void) { // change the MCU speed to 2Mhz CLKPR = (1 << CLKPCE) | (0 << CLKPS0) | (0 << CLKPS1) | (0 << CLKPS2) | (0 << CLKPS3); CLKPR = (0 << CLKPS0) | (1 << CLKPS1) | (0 << CLKPS2) | (0 << CLKPS3) | (0 << CLKPCE); // set initial port and pin states DDRB = 0; PORTB = 0; // calculate the number of leds in our configuration totalFF = sizeof(ledConfig)/sizeof(ledConfig[0]); // initiate power saving method powerSaving(); // flash leds on startup startupFlash(); // start timer based operations setupTimer(); // main loop while (1) { // determine which FF will light up next nextFF = rand() % (totalFF * 5); // funny math to manipulate the ratio of light/dark periods if (nextFF < (totalFF * 5) - 5) { nextFF = 0; } else { nextFF = nextFF - ((totalFF * 5) - 5); } // determine the sex of the FF that will light up next genderFF = rand() % 2; if (genderFF == 0) { nextDutyCycle = 255; nextDutyModifier = 32; } else { nextDutyCycle = 64; nextDutyModifier = 255; } // track the amount of time we have been running if (milliTick >= 31250) { runTime++; milliTick = 0; } // sleep after we run for a time if (runTime >= sleepTime) { sleepNow(); } } }