5252#define TIMER_LENGTH 11
5353#define TIMER_SLEEP_INDEX 8
5454
55- #define RING_PORT VPORTC
56-
5755#ifdef __AVR_AVR128DB48__ // MINI
5856
57+ #define RING_PORT VPORTC
5958#define RING_PIN_bm PIN6_bm
6059
6160#define LOWQ_PIN PIN_PB4
6261#define VOLTAGE_MEASURE_EN_PIN PIN_PB3
6362#define VOLTAGE_MEASURE_PIN PIN_PE0
6463
64+ #define EEPROM_CS_PIN PIN_PE3
65+
6566#define DEBUGGER_TX_PIN PIN_PB0
6667#define DEBUGGER_RX_PIN PIN_PB1
6768#define DEBUGGER_LED_PIN PIN_PB2
7374#define I2C1_SDA_PIN PIN_PF2
7475#define I2C1_SCL_PIN PIN_PF3
7576
77+ #define SPI_CS PIN_PB5
78+ #define SPI_MOSI PIN_PA4
79+ #define SPI_MISO PIN_PA5
80+ #define SPI_SCK PIN_PA6
81+
82+ #define SW0_PORT PORTD
83+
7684#else
7785
7886#ifdef __AVR_AVR128DB64__ // Non-Mini
7987
88+ #define RING_PORT VPORTC
8089#define RING_PIN_bm PIN4_bm
8190
8291#define LOWQ_PIN PIN_PB4
8392#define VOLTAGE_MEASURE_EN_PIN PIN_PB3
8493#define VOLTAGE_MEASURE_PIN PIN_PE0
8594
95+ #define EEPROM_CS_PIN PIN_PE3
96+
8697#define DEBUGGER_TX_PIN PIN_PB0
8798#define DEBUGGER_RX_PIN PIN_PB1
8899#define DEBUGGER_LED_PIN PIN_PB2
94105#define I2C1_SDA_PIN PIN_PF2
95106#define I2C1_SCL_PIN PIN_PF3
96107
108+ #define SPI_CS PIN_PB5
109+ #define SPI_MOSI PIN_PA4
110+ #define SPI_MISO PIN_PA5
111+ #define SPI_SCK PIN_PA6
112+
113+ #define SW0_PORT PORTD
114+
97115#else
98116#error "INCOMPATIBLE_DEVICE_SELECTED"
99117#endif
@@ -331,70 +349,119 @@ static void disablePIT(void) {
331349 RTC.PITCTRLA &= ~RTC_PITEN_bm;
332350}
333351
352+ static void setPinLowPowerMode (const uint8_t pin, const bool pull_up = true ) {
353+
354+ if (pull_up) {
355+ pinConfigure (pin,
356+ PIN_DIR_INPUT | PIN_ISC_DISABLE | PIN_PULLUP_ON |
357+ PIN_INPUT_DISABLE);
358+ } else {
359+ pinConfigure (pin, PIN_DIR_INPUT | PIN_ISC_DISABLE | PIN_INPUT_DISABLE);
360+ }
361+ }
362+
363+ static void setPinNormalInputMode (const uint8_t pin) {
364+ pinConfigure (pin, PIN_DIR_INPUT | PIN_PULLUP_OFF | PIN_INPUT_ENABLE);
365+ }
366+
367+ static void setPinNormalOutputMode (const uint8_t pin) {
368+ pinConfigure (pin, PIN_DIR_OUTPUT | PIN_PULLUP_OFF | PIN_INPUT_ENABLE);
369+ }
370+
334371static void powerDownPeripherals (void ) {
335- // LEDs
336- pinConfigure (LedCtrl.getLedPin (Led::CELL),
337- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
338- pinConfigure (LedCtrl.getLedPin (Led::CON),
339- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
340- pinConfigure (LedCtrl.getLedPin (Led::DATA),
341- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
342- pinConfigure (LedCtrl.getLedPin (Led::ERROR),
343- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
344- pinConfigure (LedCtrl.getLedPin (Led::USER),
345- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
346-
347- // Make sure that I2C pins are pulled up and there won't be a voltage drop
348- // over them over the external pull up resistors
349- pinConfigure (I2C0_SDA_PIN, PIN_DIR_OUTPUT | PIN_PULLUP_ON);
350- pinConfigure (I2C0_SCL_PIN, PIN_DIR_OUTPUT | PIN_PULLUP_ON);
351- pinConfigure (I2C1_SDA_PIN, PIN_DIR_OUTPUT | PIN_PULLUP_ON);
352- pinConfigure (I2C1_SCL_PIN, PIN_DIR_OUTPUT | PIN_PULLUP_ON);
353372
354- // Voltage measure
355- digitalWrite (VOLTAGE_MEASURE_EN_PIN, LOW);
373+ // EEPROM - Set in standby mode
374+ setPinLowPowerMode (EEPROM_CS_PIN);
375+
376+ // I2C
377+ //
378+ // We don't pull up the I2C lines as they have external pull-ups
379+ Wire.end ();
380+ Wire1.end ();
381+ setPinLowPowerMode (I2C0_SDA_PIN, false );
382+ setPinLowPowerMode (I2C0_SCL_PIN, false );
383+ setPinLowPowerMode (I2C1_SDA_PIN, false );
384+ setPinLowPowerMode (I2C1_SCL_PIN, false );
385+
386+ // SPI
387+ setPinLowPowerMode (SPI_CS);
388+ setPinLowPowerMode (SPI_MOSI);
389+ setPinLowPowerMode (SPI_MOSI);
390+ setPinLowPowerMode (SPI_SCK);
391+
392+ // Debugger, add pull-ups on pins for USART TX & RX, as well as LED pin
356393
357- // Debugger
358394 DEBUGGER_USART.CTRLB &= ~(USART_RXEN_bm | USART_TXEN_bm);
359- pinConfigure (DEBUGGER_TX_PIN,
360- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
361- pinConfigure (DEBUGGER_RX_PIN,
362- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
363- pinConfigure (DEBUGGER_LED_PIN,
364- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
365- pinConfigure (DEBUGGER_SW0_PIN,
366- PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
395+ setPinLowPowerMode (DEBUGGER_TX_PIN);
396+ setPinLowPowerMode (DEBUGGER_RX_PIN);
397+ setPinLowPowerMode (DEBUGGER_LED_PIN);
398+
399+ // Only enable pull-up for SW0 to not have current over it, but keep active
400+ // for waking the device up by the button
401+ SW0_PORT.PIN2CTRL |= PORT_PULLUPEN_bm;
402+
403+ // LEDs
404+ setPinLowPowerMode (LedCtrl.getLedPin (Led::CELL));
405+ setPinLowPowerMode (LedCtrl.getLedPin (Led::CON));
406+ setPinLowPowerMode (LedCtrl.getLedPin (Led::DATA));
407+ setPinLowPowerMode (LedCtrl.getLedPin (Led::ERROR));
408+ setPinLowPowerMode (LedCtrl.getLedPin (Led::USER));
409+
410+ // Disable ADC0, used for analogRead
411+ ADC0.CTRLA &= ~ADC_ENABLE_bm;
412+
413+ // Voltage measure enable and voltage measure pins have external pull-up
414+ setPinLowPowerMode (VOLTAGE_MEASURE_EN_PIN, false );
415+ setPinLowPowerMode (VOLTAGE_MEASURE_PIN, false );
416+
417+ // Disable millis() timer
418+ stop_millis ();
367419}
368420
369421static void powerUpPeripherals () {
370422
371- pinConfigure (LedCtrl.getLedPin (Led::CELL),
372- PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
373- pinConfigure (LedCtrl.getLedPin (Led::CON),
374- PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
375- pinConfigure (LedCtrl.getLedPin (Led::DATA),
376- PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
377- pinConfigure (LedCtrl.getLedPin (Led::ERROR),
378- PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
379- pinConfigure (LedCtrl.getLedPin (Led::USER),
380- PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
381-
382- // Make sure that I2C pins are pulled up and there won't be a voltage drop
383- // over them
384- pinConfigure (I2C0_SDA_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
385- pinConfigure (I2C0_SCL_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
386- pinConfigure (I2C1_SDA_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
387- pinConfigure (I2C1_SCL_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
423+ // Enable millis() timer
424+ restart_millis ();
388425
389426 // Voltage measure
390- digitalWrite (VOLTAGE_MEASURE_PIN, HIGH);
427+ setPinNormalInputMode (VOLTAGE_MEASURE_PIN);
428+ setPinNormalOutputMode (VOLTAGE_MEASURE_EN_PIN);
429+
430+ // ADC for analogRead
431+ init_ADC0 ();
432+
433+ // LEDs
434+ setPinNormalOutputMode (LedCtrl.getLedPin (Led::CELL));
435+ setPinNormalOutputMode (LedCtrl.getLedPin (Led::CON));
436+ setPinNormalOutputMode (LedCtrl.getLedPin (Led::DATA));
437+ setPinNormalOutputMode (LedCtrl.getLedPin (Led::ERROR));
438+ setPinNormalOutputMode (LedCtrl.getLedPin (Led::USER));
391439
392440 // Debugger
393- DEBUGGER_USART.CTRLB |= (USART_RXEN_bm | USART_TXEN_bm);
394- pinConfigure (DEBUGGER_TX_PIN, PIN_DIR_OUTPUT);
395- pinConfigure (DEBUGGER_RX_PIN, PIN_DIR_INPUT | PIN_INPUT_ENABLE);
396- pinConfigure (DEBUGGER_LED_PIN, PIN_DIR_OUTPUT);
397- pinConfigure (DEBUGGER_SW0_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
441+ setPinNormalOutputMode (DEBUGGER_TX_PIN);
442+ setPinNormalInputMode (DEBUGGER_RX_PIN);
443+ setPinNormalOutputMode (DEBUGGER_LED_PIN);
444+
445+ SW0_PORT.PIN2CTRL &= ~PORT_PULLUPEN_bm;
446+
447+ DEBUGGER_USART.CTRLB |= USART_TXEN_bm | USART_RXEN_bm;
448+
449+ // I2C
450+ setPinNormalOutputMode (I2C0_SDA_PIN);
451+ setPinNormalOutputMode (I2C0_SCL_PIN);
452+ setPinNormalOutputMode (I2C1_SDA_PIN);
453+ setPinNormalOutputMode (I2C1_SCL_PIN);
454+ Wire.begin ();
455+ Wire1.begin ();
456+
457+ // SPI
458+ setPinNormalOutputMode (SPI_CS);
459+ setPinNormalOutputMode (SPI_MOSI);
460+ setPinNormalInputMode (SPI_MISO);
461+ setPinNormalOutputMode (SPI_SCK);
462+
463+ // EEPROM
464+ setPinNormalOutputMode (EEPROM_CS_PIN);
398465}
399466
400467static void enableLDO (void ) {
@@ -403,15 +470,15 @@ static void enableLDO(void) {
403470 digitalWrite (LOWQ_PIN, HIGH);
404471
405472 // Wait a little to let LDO mode settle
406- delay (10 );
473+ delay (100 );
407474}
408475
409476static void disableLDO (void ) {
410477 pinConfigure (LOWQ_PIN, PIN_DIR_OUTPUT);
411478 digitalWrite (LOWQ_PIN, LOW);
412479
413480 // Wait a little to let PWM mode settle
414- delay (10 );
481+ delay (100 );
415482}
416483
417484void LowPowerClass::configurePowerDown (void ) {
@@ -553,7 +620,6 @@ void LowPowerClass::powerDown(const uint32_t power_down_time_seconds) {
553620
554621 const unsigned long start_time_ms = millis ();
555622
556- powerDownPeripherals ();
557623 SLPCTRL.CTRLA |= SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm;
558624
559625 Lte.end ();
@@ -564,6 +630,10 @@ void LowPowerClass::powerDown(const uint32_t power_down_time_seconds) {
564630 power_down_time_seconds -
565631 (uint32_t )(((millis () - start_time_ms) / 1000 .0f ));
566632
633+ // Need to power down the peripherals here as we want to grab the time
634+ // (millis()) from the timer before disabling it
635+ powerDownPeripherals ();
636+
567637 while (remaining_time_seconds > 0 ) {
568638
569639 sleep_cpu ();
0 commit comments