#include "o3.h" #include "gpio.h" #include "systick.h" /**************************************************************************/ /** * @brief Konverterer nummer til string * Konverterer et nummer mellom 0 og 99 til string *****************************************************************************/ void int_to_string(char *timestamp, unsigned int offset, int i) { if (i > 99) { timestamp[offset] = '9'; timestamp[offset + 1] = '9'; return; } while (i > 0) { if (i >= 10) { i -= 10; timestamp[offset]++; } else { timestamp[offset + 1] = '0' + i; i = 0; } } } /**************************************************************************/ /** * @brief Konverterer 3 tall til en timestamp-string * timestamp-argumentet må være et array med plass til (minst) 7 elementer. * Det kan deklareres i funksjonen som kaller som "char timestamp[7];" * Kallet blir dermed: * char timestamp[7]; * time_to_string(timestamp, h, m, s); *****************************************************************************/ void time_to_string(char *timestamp, int h, int m, int s) { timestamp[0] = '0'; timestamp[1] = '0'; timestamp[2] = '0'; timestamp[3] = '0'; timestamp[4] = '0'; timestamp[5] = '0'; timestamp[6] = '\0'; int_to_string(timestamp, 0, h); int_to_string(timestamp, 2, m); int_to_string(timestamp, 4, s); } /* -------------------------------------------------------------------------- */ typedef struct { word CTRL; word MODEL; word MODEH; word DOUT; word DOUTSET; word DOUTCLR; word DOUTTGL; word DIN; word PINLOCKN; } gpio_port_map_t; typedef volatile struct { gpio_port_map_t ports[6]; word unused_space[10]; word EXTIPSELL; word EXTIPSELH; word EXTIRISE; word EXTIFALL; word IEN; word IF; word IFS; word IFC; word ROUTE; word INSENSE; word LOCK; word CTRL; word CMD; word EM4WUEN; word EM4WUPOL; word EM4WUCAUSE; } gpio_t; typedef volatile struct { word CTRL; word LOAD; word VAL; word CALIB; } systick_t; static volatile gpio_t* const gpio = (gpio_t*) GPIO_BASE; static volatile systick_t* const systick = (systick_t*) SYSTICK_BASE; #define GPIO_LED GPIO_PORT_E #define GPIO_PB GPIO_PORT_B #define LED_PIN 2 #define PB0_PIN 9 #define PB1_PIN 10 /* -------------------------------------------------------------------------- */ enum PROGRAM_STATE { ADD_SECS, ADD_MINS, ADD_HOURS, COUNTDOWN, ALARM, PROGRAM_STATE_SIZE, }; static struct { char display[7]; unsigned char hours; unsigned char minutes; unsigned char seconds; unsigned char programState; } state; void initializeState() { state.hours = 0; state.minutes = 0; state.seconds = 0; state.programState = ADD_SECS; } void initializeInterruptHandlers() { // Setup SYSTICK systick->CTRL = 0b111; systick->LOAD = FREQUENCY; systick->VAL = 1; // Setup LED volatile word* setting; setting = &gpio->ports[GPIO_LED].MODEL; *setting &= ~(0xF << (4 * LED_PIN)); *setting += GPIO_MODE_OUTPUT << (4 * LED_PIN); // Setup buttons for (char i=0; i<2; i++) { setting = i ? &gpio->ports[GPIO_PB].MODEH : &gpio->EXTIPSELH; *setting &= ~(0xFF << 4); *setting += 0x110; word button = i ? PB0_PIN : PB1_PIN; gpio->EXTIFALL |= (1 << button); gpio->IEN |= (1 << button); } } void activateAlarm() { state.programState = ALARM; gpio->ports[GPIO_LED].DOUTSET = 1 << LED_PIN; } void deactivateAlarm() { gpio->ports[GPIO_LED].DOUTCLR = 1 << LED_PIN; } void turnToNextState() { if (state.programState == COUNTDOWN) return; if (state.programState == ALARM) deactivateAlarm(); state.programState++; state.programState %= PROGRAM_STATE_SIZE; } void updateScreen() { time_to_string(state.display, state.hours, state.minutes, state.seconds); lcd_write(state.display); } /* -------------------------------------------------------------------------- */ void SysTick_Handler() { gpio->ports[GPIO_LED].DOUTTGL = 1; if (state.programState != COUNTDOWN) return; if (!state.seconds) { if (!state.minutes) { if (!state.hours) { activateAlarm(); return; } state.hours--; state.minutes = 60; return; } state.minutes--; state.seconds = 60; return; } state.seconds--; } // PB0 void GPIO_ODD_IRQHandler() { switch (state.programState) { case ADD_SECS: state.seconds++; state.seconds %= 60; break; case ADD_MINS: state.minutes++; state.minutes %= 60; break; case ADD_HOURS: state.hours++; break; } gpio->IFC = 1 << PB0_PIN; } // PB1 void GPIO_EVEN_IRQHandler() { turnToNextState(); gpio->IFC = 1 << PB1_PIN; } /* -------------------------------------------------------------------------- */ int main(void) { init(); initializeInterruptHandlers(); initializeState(); for (;;) { updateScreen(); __asm__("WFI"); } return 0; }