fw: Implement power management

This commit is contained in:
Markus Koch 2020-07-30 19:57:46 +02:00
parent 9e9e2ff5c4
commit e26471381a
6 changed files with 102 additions and 11 deletions

View File

@ -1,9 +1,10 @@
MCU=atmega88 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 LDFLAGS=-Wl,-gc-sections -Wl,-relax
CC=avr-gcc CC=avr-gcc
TARGET=main 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 all: $(TARGET).hex

View File

@ -6,6 +6,7 @@
#include "input.h" #include "input.h"
#include "systick.h" #include "systick.h"
#include "batmon.h" #include "batmon.h"
#include "pm.h"
#define PORT_SPI(t) t##B #define PORT_SPI(t) t##B
#define PIN_SPI_CS (1 << 2) #define PIN_SPI_CS (1 << 2)
@ -66,28 +67,42 @@ uint8_t spi_proc()
return spi_cs; 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_gotoxy(0, 0);
lcd_puts_p(PSTR("== Internet Radio ==")); lcd_puts_p(PSTR("== Internet Radio =="));
lcd_drawLine(0, 9, 120, 9, WHITE); lcd_drawLine(0, 9, 120, 9, WHITE);
lcd_gotoxy(0, 2); lcd_gotoxy(0, 2);
lcd_puts_p(PSTR("Starting up.")); lcd_puts_p(msg1);
lcd_gotoxy(0, 3); lcd_gotoxy(0, 3);
lcd_puts_p(PSTR("Please wait...")); lcd_puts_p(msg2);
lcd_display(); lcd_display();
} }
int main() int main()
{ {
char *post_msg;
MCUSR &= ~(1 << WDRF);
WDTCSR = (1 << WDCE);
cli(); cli();
lcd_startup(); suspend();
lcd_init(LCD_DISP_ON);
lcd_title(PSTR("Starting IOC Rev."), PSTR(GITREV));
spi_init(); spi_init();
systick_init(); systick_init();
input_init(); input_init();
batmon_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); _delay_ms(10);

View File

@ -47,10 +47,7 @@
#include "lcd.h" #include "lcd.h"
#include "font.h" #include "font.h"
#include <string.h> #include <string.h>
#if defined SPI
#include <util/delay.h> #include <util/delay.h>
#endif
static struct { static struct {
uint8_t x; uint8_t x;
@ -139,6 +136,11 @@ void lcd_data(uint8_t data[], uint16_t size) {
#pragma mark - #pragma mark -
#pragma mark GENERAL FUNCTIONS #pragma mark GENERAL FUNCTIONS
void lcd_init(uint8_t dispAttr){ 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 #if defined I2C
i2c_init(); i2c_init();
#elif defined SPI #elif defined SPI

View File

@ -74,6 +74,8 @@ extern "C" {
// e.g. 8 bit slave-adress: // e.g. 8 bit slave-adress:
// 0x78 = adress 0x3C with cleared r/w-bit (write-mode) // 0x78 = adress 0x3C with cleared r/w-bit (write-mode)
#define PORT_LCDP(t) t##C
#define PIN_LCDP (1 << 3)
#ifdef I2C #ifdef I2C
#include "i2c.h" // library for I2C-communication #include "i2c.h" // library for I2C-communication

64
firmware/pm.c Normal file
View File

@ -0,0 +1,64 @@
#include <avr/io.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#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;
}

7
firmware/pm.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef PM_H
#define PM_H
#include <avr/io.h>
void suspend();
#endif // PM_H