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
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

View File

@ -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);

View File

@ -47,10 +47,7 @@
#include "lcd.h"
#include "font.h"
#include <string.h>
#if defined SPI
#include <util/delay.h>
#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

View File

@ -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

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