diff --git a/ion/include/ion.h b/ion/include/ion.h index 2654a0a43..da2313b55 100644 --- a/ion/include/ion.h +++ b/ion/include/ion.h @@ -6,6 +6,7 @@ #include #include #include +#include /* ION is not your regular library. It is a library you link against, but it diff --git a/ion/include/ion/power.h b/ion/include/ion/power.h new file mode 100644 index 000000000..ae4a6747a --- /dev/null +++ b/ion/include/ion/power.h @@ -0,0 +1,12 @@ +#ifndef ION_POWER_H +#define ION_POWER_H + +namespace Ion { +namespace Power { + +void suspend(); + +} +} + +#endif diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index 4ea83d014..374e40ae0 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -6,6 +6,7 @@ objs += $(addprefix ion/src/device/, \ heap.o\ keyboard.o\ led.o\ + power.o\ ) # When using the register.h C++ file in production mode, we expect the compiler diff --git a/ion/src/device/device.cpp b/ion/src/device/device.cpp index eef8e3fb4..6fe1064ae 100644 --- a/ion/src/device/device.cpp +++ b/ion/src/device/device.cpp @@ -53,6 +53,7 @@ void Ion::Device::initClocks() { RCC.APB1ENR()->setTIM3EN(true); RCC.APB2ENR()->setADC1EN(true); + RCC.APB2ENR()->setSYSCFGEN(true); } void Ion::Device::initFPU() { diff --git a/ion/src/device/keyboard.cpp b/ion/src/device/keyboard.cpp index 7ddb9fe30..89a843a50 100644 --- a/ion/src/device/keyboard.cpp +++ b/ion/src/device/keyboard.cpp @@ -79,7 +79,11 @@ bool keyDown(Key k) { // Private Ion::Keyboard::Device methods -void Ion::Keyboard::Device::init() { +namespace Ion { +namespace Keyboard { +namespace Device { + +void init() { for (uint8_t i=0; isetMode(pin, GPIO::MODER::Mode::Output); @@ -92,3 +96,32 @@ void Ion::Keyboard::Device::init() { ColumnGPIO.PUPDR()->setPull(pin, GPIO::PUPDR::Pull::Up); } } + +void generateWakeUpEventForKey(Ion::Keyboard::Key k) { + // We're driving the rows and reading the columns. + int row = rowForKey(k); + for (uint8_t i=0; iset(pin, state); + } + + uint8_t column = columnForKey(k); + uint8_t columnPin = ColumnPins[column]; + + SYSCFG.EXTICR1()->setEXTI(columnPin, ColumnGPIO); + + EXTI.EMR()->set(columnPin, true); + + /* When the key is pressed, it will go from 1 (because it's pulled up) to + * zero (because it's connected to the open-drain output. In other words, + * we're waiting for a falling edge. */ + EXTI.FTSR()->set(columnPin, true); +} + +} +} +} diff --git a/ion/src/device/keyboard.h b/ion/src/device/keyboard.h index c9c102def..13d79c400 100644 --- a/ion/src/device/keyboard.h +++ b/ion/src/device/keyboard.h @@ -1,6 +1,7 @@ #ifndef ION_DEVICE_KEYBOARD_H #define ION_DEVICE_KEYBOARD_H +#include #include "regs/regs.h" namespace Ion { @@ -43,6 +44,8 @@ inline uint8_t columnForKey(Ion::Keyboard::Key key) { return (int)key%numberOfColumns; } +void generateWakeUpEventForKey(Ion::Keyboard::Key k); + } } } diff --git a/ion/src/device/power.cpp b/ion/src/device/power.cpp new file mode 100644 index 000000000..52a1bb4d1 --- /dev/null +++ b/ion/src/device/power.cpp @@ -0,0 +1,10 @@ +#include +#include +#include "keyboard.h" + +void Ion::Power::suspend() { + Display::setBacklightIntensity(0); + Keyboard::Device::generateWakeUpEventForKey(Ion::Keyboard::Key::J1); + asm("wfe"); + Display::setBacklightIntensity(0xFF); +} diff --git a/ion/src/device/regs/exti.h b/ion/src/device/regs/exti.h new file mode 100644 index 000000000..a70a7cfc1 --- /dev/null +++ b/ion/src/device/regs/exti.h @@ -0,0 +1,30 @@ +#ifndef REGS_EXTI_H +#define REGS_EXTI_H + +#include "register.h" + +class EXTI { +public: + class MaskRegister : Register32 { + public: + bool get(int index) { return (bool)getBitRange(index, index); } + void set(int index, bool state) volatile { setBitRange(index, index, state); } + }; + + //class IMR : public MaskRegister { }; + class EMR : public MaskRegister { }; + class FTSR : public MaskRegister { }; + + constexpr EXTI() {}; + //REGS_REGISTER_AT(IMR, 0x00); + REGS_REGISTER_AT(EMR, 0x04); + REGS_REGISTER_AT(FTSR, 0x0C); +private: + constexpr uint32_t Base() const { + return 0x40013C00; + } +}; + +constexpr EXTI EXTI; + +#endif diff --git a/ion/src/device/regs/gpio.h b/ion/src/device/regs/gpio.h index 54535829a..918594473 100644 --- a/ion/src/device/regs/gpio.h +++ b/ion/src/device/regs/gpio.h @@ -69,6 +69,7 @@ public: }; constexpr GPIO(int i) : m_index(i) {} + operator int() const { return m_index; } REGS_REGISTER_AT(MODER, 0x00); REGS_REGISTER_AT(OTYPER, 0x04); REGS_REGISTER_AT(PUPDR, 0x0C); diff --git a/ion/src/device/regs/rcc.h b/ion/src/device/regs/rcc.h index 3f2ee432e..5be8b3f3f 100644 --- a/ion/src/device/regs/rcc.h +++ b/ion/src/device/regs/rcc.h @@ -36,6 +36,7 @@ public: public: REGS_BOOL_FIELD(TIM1EN, 0); REGS_BOOL_FIELD(ADC1EN, 8); + REGS_BOOL_FIELD(SYSCFGEN, 14); }; constexpr RCC() {}; diff --git a/ion/src/device/regs/regs.h b/ion/src/device/regs/regs.h index 209543e1a..586b84e16 100644 --- a/ion/src/device/regs/regs.h +++ b/ion/src/device/regs/regs.h @@ -2,10 +2,12 @@ #define REGS_REGS_H #include "adc.h" +#include "exti.h" #include "cm4.h" #include "fsmc.h" #include "rcc.h" #include "gpio.h" +#include "syscfg.h" #include "tim.h" #endif diff --git a/ion/src/device/regs/syscfg.h b/ion/src/device/regs/syscfg.h new file mode 100644 index 000000000..c13fbe612 --- /dev/null +++ b/ion/src/device/regs/syscfg.h @@ -0,0 +1,25 @@ +#ifndef REGS_SYSCFG_H +#define REGS_SYSCFG_H + +#include "register.h" + +#include "gpio.h" + +class SYSCFG { +public: + class EXTICR1 : Register32 { + public: + void setEXTI(int index, GPIO gpio) volatile { setBitRange(4*index+3, 4*index, (uint32_t)gpio); } + }; + + constexpr SYSCFG() {}; + REGS_REGISTER_AT(EXTICR1, 0x08); +private: + constexpr uint32_t Base() const { + return 0x40013800; + } +}; + +constexpr SYSCFG SYSCFG; + +#endif