diff --git a/midi2cv/bootloader/bootloader.cc b/midi2cv/bootloader/bootloader.cc index ddb002c..233ff91 100644 --- a/midi2cv/bootloader/bootloader.cc +++ b/midi2cv/bootloader/bootloader.cc @@ -1,13 +1,25 @@ #include #include "stmlib/system/bootloader_utils.h" +#include "midi2cv/drivers/eco_display.h" +#include using namespace stmlib; const uint32_t kStartAddress = 0x08008000; -int main(void) { +EcoDisplay display; + +int main(void) +{ SystemInit(); + + display.Init(); + + display.u8x8()->setFont(u8x8_font_amstrad_cpc_extended_r); + display.u8x8()->drawString(0, 0, "Moin"); + for (int i = 0; i < 100000000; i++) + ; Uninitialize(); JumpTo(kStartAddress); } diff --git a/midi2cv/bootloader/makefile b/midi2cv/bootloader/makefile index 154b635..7028293 100644 --- a/midi2cv/bootloader/makefile +++ b/midi2cv/bootloader/makefile @@ -8,10 +8,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: -# +# # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,7 +19,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -# +# # See http://creativecommons.org/licenses/MIT/ for more information. # System specifications diff --git a/midi2cv/drivers/base_display.cc b/midi2cv/drivers/base_display.cc new file mode 100644 index 0000000..dae2e46 --- /dev/null +++ b/midi2cv/drivers/base_display.cc @@ -0,0 +1,91 @@ +#include "base_display.h" +#include "spi_mode.h" +#include +#include + +static const uint16_t kPinEnable = GPIO_Pin_2; +static const uint16_t kPinReset = GPIO_Pin_0; +static const uint16_t kPinDataCommand = GPIO_Pin_9; + +uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t* u8x8, + U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, + U8X8_UNUSED void* arg_ptr) +{ + return 1; +} + +uint8_t u8x8_byte_4wire_stm32_spi(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, + void* arg_ptr) +{ + uint8_t* data; + switch (msg) { + case U8X8_MSG_BYTE_SEND: + data = (uint8_t*)arg_ptr; + while (arg_int > 0) { + while (!(SPI2->SR & SPI_SR_TXE)) { + } + SPI_SendData8(SPI2, (uint8_t)*data); + arg_int--; + data++; + } + break; + case U8X8_MSG_BYTE_INIT: + break; + case U8X8_MSG_BYTE_SET_DC: + if (arg_int) + GPIO_WriteBit(GPIOB, kPinDataCommand, Bit_SET); + else + GPIO_WriteBit(GPIOB, kPinDataCommand, Bit_RESET); + break; + case U8X8_MSG_BYTE_START_TRANSFER: + InitSPI(SPI_MODE_DISPLAY); + GPIO_WriteBit(GPIOB, kPinEnable, Bit_RESET); + break; + case U8X8_MSG_BYTE_END_TRANSFER: + GPIO_WriteBit(GPIOB, kPinEnable, Bit_SET); + break; + default: + return 0; + } + return 1; +} + +void BaseDisplay::Init() +{ + // init SS/CS/RST GPIO + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); + + GPIO_InitTypeDef gpio_init; + gpio_init.GPIO_Mode = GPIO_Mode_OUT; + gpio_init.GPIO_OType = GPIO_OType_PP; + gpio_init.GPIO_Speed = GPIO_Speed_50MHz; + gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL; + gpio_init.GPIO_Pin = kPinEnable | kPinReset | kPinDataCommand; + GPIO_Init(GPIOB, &gpio_init); + + GPIO_WriteBit(GPIOB, kPinEnable, Bit_SET); + + // init AF GPIO + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); + + gpio_init.GPIO_Mode = GPIO_Mode_AF; + gpio_init.GPIO_OType = GPIO_OType_PP; + gpio_init.GPIO_Speed = GPIO_Speed_50MHz; + gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL; + gpio_init.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_14 | GPIO_Pin_15; + GPIO_Init(GPIOB, &gpio_init); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_5); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_5); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_5); + + // init SPI + RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); + SPI_I2S_DeInit(SPI2); + // Initialize SPI + InitSPI(SPI_MODE_DISPLAY); + GPIO_WriteBit(GPIOB, kPinReset, Bit_RESET); + asm("nop"); + + GPIO_WriteBit(GPIOB, kPinReset, Bit_SET); + InitGLib(); +} diff --git a/midi2cv/drivers/base_display.h b/midi2cv/drivers/base_display.h new file mode 100644 index 0000000..1be2dc0 --- /dev/null +++ b/midi2cv/drivers/base_display.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +extern uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t* u8x8, + U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, + U8X8_UNUSED void* arg_ptr); + +extern uint8_t u8x8_byte_4wire_stm32_spi(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, + void* arg_ptr); + +class BaseDisplay { + public: + void Init(); + + protected: + virtual void InitGLib(); +}; diff --git a/midi2cv/drivers/display.cc b/midi2cv/drivers/display.cc index 01c2e25..aff667b 100644 --- a/midi2cv/drivers/display.cc +++ b/midi2cv/drivers/display.cc @@ -8,63 +8,17 @@ using namespace stmlib; -static const uint16_t kPinEnable = GPIO_Pin_2; -static const uint16_t kPinReset = GPIO_Pin_0; -static const uint16_t kPinDataCommand = GPIO_Pin_9; - static uint8_t* default_buf; static uint8_t second_buf[1024]; static uint8_t* output_buf; -uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t* u8x8, - U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, - U8X8_UNUSED void* arg_ptr) -{ - return 1; -} - -uint8_t u8x8_byte_4wire_hw_spi(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, - void* arg_ptr) -{ - uint8_t* data; - switch (msg) { - case U8X8_MSG_BYTE_SEND: - data = (uint8_t*)arg_ptr; - while (arg_int > 0) { - while (!(SPI2->SR & SPI_SR_TXE)) { - } - SPI_SendData8(SPI2, (uint8_t)*data); - arg_int--; - data++; - } - break; - case U8X8_MSG_BYTE_INIT: - break; - case U8X8_MSG_BYTE_SET_DC: - if (arg_int) - GPIO_WriteBit(GPIOB, kPinDataCommand, Bit_SET); - else - GPIO_WriteBit(GPIOB, kPinDataCommand, Bit_RESET); - break; - case U8X8_MSG_BYTE_START_TRANSFER: - InitSPI(SPI_MODE_DISPLAY); - GPIO_WriteBit(GPIOB, kPinEnable, Bit_RESET); - break; - case U8X8_MSG_BYTE_END_TRANSFER: - GPIO_WriteBit(GPIOB, kPinEnable, Bit_SET); - break; - default: - return 0; - } - return 1; -} class U8G2_SH1106_128x64_NONAME_F_SPI : public U8G2 { public: U8G2_SH1106_128x64_NONAME_F_SPI() : U8G2() { - u8g2_Setup_sh1106_128x64_noname_f(&this->u8g2, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_stm32_gpio_and_delay); + u8g2_Setup_sh1106_128x64_noname_f(&this->u8g2, U8G2_R0, u8x8_byte_4wire_stm32_spi, u8x8_stm32_gpio_and_delay); output_buf = default_buf = this->u8g2.tile_buf_ptr; /*u8g2_InitDisplay(&u8g2_); u8g2_SetContrast(&u8g2_, 255); @@ -79,46 +33,6 @@ U8G2* Display::u8g2() return &u8g2_; } -void Display::Init() -{ - // init SS/CS/RST GPIO - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); - - GPIO_InitTypeDef gpio_init; - gpio_init.GPIO_Mode = GPIO_Mode_OUT; - gpio_init.GPIO_OType = GPIO_OType_PP; - gpio_init.GPIO_Speed = GPIO_Speed_50MHz; - gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL; - gpio_init.GPIO_Pin = kPinEnable | kPinReset | kPinDataCommand; - GPIO_Init(GPIOB, &gpio_init); - - GPIO_WriteBit(GPIOB, kPinEnable, Bit_SET); - - // init AF GPIO - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); - - gpio_init.GPIO_Mode = GPIO_Mode_AF; - gpio_init.GPIO_OType = GPIO_OType_PP; - gpio_init.GPIO_Speed = GPIO_Speed_50MHz; - gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL; - gpio_init.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_14 | GPIO_Pin_15; - GPIO_Init(GPIOB, &gpio_init); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_5); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_5); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_5); - - // init SPI - RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); - SPI_I2S_DeInit(SPI2); - // Initialize SPI - InitSPI(SPI_MODE_DISPLAY); - GPIO_WriteBit(GPIOB, kPinReset, Bit_RESET); - asm("nop"); - - GPIO_WriteBit(GPIOB, kPinReset, Bit_SET); - InitGLib(); -} - void Display::InitGLib() { u8g2_.begin(); diff --git a/midi2cv/drivers/display.h b/midi2cv/drivers/display.h index 30694d4..74591ef 100644 --- a/midi2cv/drivers/display.h +++ b/midi2cv/drivers/display.h @@ -2,25 +2,32 @@ #define MIDI2CV_DRIVERS_DISPLAY_H #include "stmlib/stmlib.h" -#include +#include "base_display.h" #include +#include #define DISPLAY_WIDTH 128 #define DISPLAY_HEIGHT 64 -class Display { -public: - Display() {} - ~Display() {} +extern uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t* u8x8, + U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, + U8X8_UNUSED void* arg_ptr); - void Init(); - U8G2* u8g2(); - void Flush(); - void Swap(); +extern uint8_t u8x8_byte_4wire_stm32_spi(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, + void* arg_ptr); -private: - DISALLOW_COPY_AND_ASSIGN(Display); - void InitGLib(); +class Display : public BaseDisplay { + public: + Display() {} + ~Display() {} + + U8G2* u8g2(); + void Flush(); + void Swap(); + + private: + DISALLOW_COPY_AND_ASSIGN(Display); + void InitGLib(); }; -extern Display display; + #endif diff --git a/midi2cv/drivers/eco_display.h b/midi2cv/drivers/eco_display.h new file mode 100644 index 0000000..fee23b9 --- /dev/null +++ b/midi2cv/drivers/eco_display.h @@ -0,0 +1,28 @@ +#pragma once + +#include "base_display.h" +#include + +class U8X8_SH1106_128X64_NONAME_4W_SW_SPI : public U8X8 { + public: + U8X8_SH1106_128X64_NONAME_4W_SW_SPI() + : U8X8() + { + u8x8_Setup(getU8x8(), u8x8_d_sh1106_128x64_noname, u8x8_cad_001, u8x8_byte_4wire_stm32_spi, u8x8_stm32_gpio_and_delay); + } +}; + +class EcoDisplay : public BaseDisplay { + protected: + void InitGLib() { + this->u8x8()->begin(); + } + + public: + U8X8* u8x8() { + return &this->instance; + } + + U8X8_SH1106_128X64_NONAME_4W_SW_SPI instance; + +}; diff --git a/midi2cv/makefile b/midi2cv/makefile index 001d276..dff52ce 100644 --- a/midi2cv/makefile +++ b/midi2cv/makefile @@ -30,6 +30,7 @@ SYSCLOCK = SYSCLK_FREQ_72MHz FAMILY = f37x # USB = enabled U8G2 = enabled +PRINTF_FLOATS = enabled APPLICATION_LARGE = TRUE BOOTLOADER = midi2cv_bootloader diff --git a/midi2cv/midi2cv.cc b/midi2cv/midi2cv.cc index dbe7740..dc0cb66 100644 --- a/midi2cv/midi2cv.cc +++ b/midi2cv/midi2cv.cc @@ -21,7 +21,7 @@ Settings settings; Part parts[PART_COUNT]; Part* part_pointers[PART_COUNT] = { &parts[0], &parts[1], &parts[2], &parts[3] }; -UI ui(part_pointers, &settings); +UI ui(part_pointers, &display, &settings); // Default interrupt handlers. extern "C" { diff --git a/midi2cv/settings.h b/midi2cv/settings.h index fb20b4b..006c135 100644 --- a/midi2cv/settings.h +++ b/midi2cv/settings.h @@ -65,7 +65,7 @@ class Settings { State state_; stmlib::ChunkStorage< - 0x08004000, + 0x08006000, 0x08008000, PersistentData, State> diff --git a/midi2cv/ui.cc b/midi2cv/ui.cc index f027d52..86355e6 100644 --- a/midi2cv/ui.cc +++ b/midi2cv/ui.cc @@ -14,12 +14,13 @@ using namespace stmlib; const uint32_t kEncoderLongPressTime = 600; -UI::UI(Part** part_pointers, Settings* settings) - : main_menu(part_pointers) +UI::UI(Part** part_pointers, Display* display, Settings* settings) + : settings(settings) + , display(display) + , main_menu(part_pointers) , parts(part_pointers) { this->input_queue.Init(); - this->settings = settings; LoadState(); } @@ -53,16 +54,16 @@ void UI::Poll() void UI::Draw() { - display.u8g2()->clearBuffer(); + this->display->u8g2()->clearBuffer(); - main_menu.render(display.u8g2(), 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); + main_menu.render(this->display->u8g2(), 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); - display.Swap(); + this->display->Swap(); } void UI::LoadState() { - for(size_t i = 0; i < PART_COUNT; i++) + for (size_t i = 0; i < PART_COUNT; i++) this->parts[i]->data = settings->part(i); } @@ -77,7 +78,7 @@ void UI::SaveState() void UI::Flush() { - display.Flush(); + this->display->Flush(); } void UI::DoEvents() diff --git a/midi2cv/ui.h b/midi2cv/ui.h index b24c2d1..15796fe 100644 --- a/midi2cv/ui.h +++ b/midi2cv/ui.h @@ -7,11 +7,12 @@ #include "config.h" #include "settings.h" #include "ui/main_menu.h" -#include + +#include "drivers/display.h" class UI { public: - UI(Part** part_pointers, Settings* settings); + UI(Part** part_pointers, Display* display, Settings* settings); ~UI() {} void Poll(); @@ -23,6 +24,8 @@ class UI { Settings* settings; + Display* display; + bool long_press_event_sent_; uint32_t start_stop_press_time_; bool encoder_long_press_event_sent_; diff --git a/stmlib b/stmlib index 99e1ad5..b5f84c6 160000 --- a/stmlib +++ b/stmlib @@ -1 +1 @@ -Subproject commit 99e1ad5fb7b241e13ec780c00ef1c3fd0200fdac +Subproject commit b5f84c61b8a10dbba36f0ba12877ffde4b42d199