From e26471381ab30057104465adbcfef28738171261 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Thu, 30 Jul 2020 19:57:46 +0200 Subject: [PATCH] fw: Implement power management --- firmware/Makefile | 5 +-- firmware/main.c | 25 ++++++++++++--- firmware/oled-display/lcd.c | 8 +++-- firmware/oled-display/lcd.h | 4 ++- firmware/pm.c | 64 +++++++++++++++++++++++++++++++++++++ firmware/pm.h | 7 ++++ 6 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 firmware/pm.c create mode 100644 firmware/pm.h diff --git a/firmware/Makefile b/firmware/Makefile index b716d96..2f710ac 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -1,9 +1,10 @@ MCU=atmega88 -CFLAGS=-g -Wall -Wno-multichar -Wno-overflow -mcall-prologues -mmcu=$(MCU) -O2 -DF_CPU=8000000 -IAVR-SSD1306/Files/ +gitrev=$(shell git describe --tags --dirty --always) +CFLAGS=-g -Wall -Wno-multichar -Wno-overflow -mcall-prologues -mmcu=$(MCU) -O2 -DF_CPU=8000000 -DGITREV=\"$(gitrev)\" -IAVR-SSD1306/Files/ LDFLAGS=-Wl,-gc-sections -Wl,-relax CC=avr-gcc TARGET=main -OBJECT_FILES=main.o batmon.o input.o systick.o oled-display/font.o oled-display/i2c.o oled-display/lcd.o +OBJECT_FILES=main.o pm.o batmon.o input.o systick.o oled-display/font.o oled-display/i2c.o oled-display/lcd.o all: $(TARGET).hex diff --git a/firmware/main.c b/firmware/main.c index 25a0f0b..e25f14b 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -6,6 +6,7 @@ #include "input.h" #include "systick.h" #include "batmon.h" +#include "pm.h" #define PORT_SPI(t) t##B #define PIN_SPI_CS (1 << 2) @@ -66,28 +67,42 @@ uint8_t spi_proc() return spi_cs; } -void lcd_startup() +void lcd_title(const char *msg1, const char *msg2) { - lcd_init(LCD_DISP_ON); + lcd_clrscr(); lcd_gotoxy(0, 0); lcd_puts_p(PSTR("== Internet Radio ==")); lcd_drawLine(0, 9, 120, 9, WHITE); lcd_gotoxy(0, 2); - lcd_puts_p(PSTR("Starting up.")); + lcd_puts_p(msg1); lcd_gotoxy(0, 3); - lcd_puts_p(PSTR("Please wait...")); + lcd_puts_p(msg2); lcd_display(); } int main() { + char *post_msg; + + MCUSR &= ~(1 << WDRF); + WDTCSR = (1 << WDCE); cli(); - lcd_startup(); + suspend(); + + lcd_init(LCD_DISP_ON); + lcd_title(PSTR("Starting IOC Rev."), PSTR(GITREV)); spi_init(); systick_init(); input_init(); batmon_init(); + if (post_msg = post()) { + lcd_title(PSTR("POST Error!"), post_msg); + _delay_ms(2000); + reset(); + } + + lcd_title(PSTR("Starting up."), PSTR("Please wait...")); _delay_ms(10); diff --git a/firmware/oled-display/lcd.c b/firmware/oled-display/lcd.c index 37ebf2d..64000c3 100644 --- a/firmware/oled-display/lcd.c +++ b/firmware/oled-display/lcd.c @@ -47,10 +47,7 @@ #include "lcd.h" #include "font.h" #include - -#if defined SPI #include -#endif static struct { uint8_t x; @@ -139,6 +136,11 @@ void lcd_data(uint8_t data[], uint16_t size) { #pragma mark - #pragma mark GENERAL FUNCTIONS void lcd_init(uint8_t dispAttr){ + PORT_LCDP(DDR) |= PIN_LCDP; + PORT_LCDP(PORT) &= ~(PIN_LCDP); + _delay_ms(100); + PORT_LCDP(PORT) |= PIN_LCDP; + _delay_ms(100); #if defined I2C i2c_init(); #elif defined SPI diff --git a/firmware/oled-display/lcd.h b/firmware/oled-display/lcd.h index a05ca2e..4f6741c 100644 --- a/firmware/oled-display/lcd.h +++ b/firmware/oled-display/lcd.h @@ -74,7 +74,9 @@ extern "C" { // e.g. 8 bit slave-adress: // 0x78 = adress 0x3C with cleared r/w-bit (write-mode) - +#define PORT_LCDP(t) t##C +#define PIN_LCDP (1 << 3) + #ifdef I2C #include "i2c.h" // library for I2C-communication // if you want to use other lib for I2C diff --git a/firmware/pm.c b/firmware/pm.c new file mode 100644 index 0000000..c81a535 --- /dev/null +++ b/firmware/pm.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include "pm.h" + +static void disable_periphery() +{ + cli(); + WDTCSR = 0; + TWCR = 0; + SPCR = 0; + ADCSRA = 0; + DDRB = 0; + DDRC = 0; + DDRD = 0; + PORTB = 0; + PORTC = 0; + PORTD = (1 << 2); // Pullup for INT0 +} + +void suspend() +{ + disable_periphery(); + + EICRA = 0; + EIMSK = (1 << INT0); + SMCR = (1 << SM1) | (1 << SE); + sei(); + sleep_cpu(); + cli(); + + _delay_ms(50); + while (!(PIND & (1 << 2))); + _delay_ms(50); +} + +ISR(INT0_vect) +{ + return; +} + +void reset() +{ + disable_periphery(); + // WDTCSR = (1 << WDE) | (1 << WDP2); + // For some reason, the WD reset locks up my chip, + // so let's just jump to the reset vector directly. + asm("ldi R16,0x00"); + asm("push R16"); + asm("push R16"); + asm("push R16"); + asm("push R16"); + asm("ret"); + while (1); +} + +char* post() +{ + // TODO: Implement battery voltage check + _delay_ms(500); + return 0; +} diff --git a/firmware/pm.h b/firmware/pm.h new file mode 100644 index 0000000..d4ed08b --- /dev/null +++ b/firmware/pm.h @@ -0,0 +1,7 @@ +#ifndef PM_H +#define PM_H +#include + +void suspend(); + +#endif // PM_H