mirror of
https://github.com/jhbruhn/eurorack.git
synced 2025-03-15 11:05:49 +00:00
Display driver fixes, UI
This commit is contained in:
parent
49632d8cfc
commit
f594aa9f43
8 changed files with 195 additions and 205 deletions
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
using namespace stmlib;
|
using namespace stmlib;
|
||||||
|
|
||||||
const uint32_t kStartAddress = 0x08001000;
|
const uint32_t kStartAddress = 0x08008000;
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
SystemInit();
|
SystemInit();
|
||||||
|
|
|
@ -24,12 +24,11 @@
|
||||||
|
|
||||||
# System specifications
|
# System specifications
|
||||||
F_CRYSTAL = 8000000L
|
F_CRYSTAL = 8000000L
|
||||||
F_CPU = 24000000L
|
F_CPU = 72000000L
|
||||||
SYSCLOCK = SYSCLK_FREQ_24MHz
|
SYSCLOCK = SYSCLK_FREQ_72MHz
|
||||||
FAMILY = f10x
|
FAMILY = f37x
|
||||||
DENSITY = md
|
|
||||||
MEMORY_MODE = flash
|
MEMORY_MODE = flash
|
||||||
|
U8G2 = enabled
|
||||||
# USB = enabled
|
# USB = enabled
|
||||||
|
|
||||||
# Preferred upload command
|
# Preferred upload command
|
||||||
|
|
|
@ -1,176 +1,122 @@
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
|
#include "stmlib/system/system_clock.h"
|
||||||
|
#include "stmlib/utils/random.h"
|
||||||
#include <stm32f37x_conf.h>
|
#include <stm32f37x_conf.h>
|
||||||
#include <u8g2.h>
|
#include <u8g2.h>
|
||||||
// SH1106 command definitions
|
|
||||||
#define SH1106_CMD_SETMUX (uint8_t)0xA8 // Set multiplex ratio (N, number of lines active on display)
|
|
||||||
#define SH1106_CMD_SETOFFS (uint8_t)0xD3 // Set display offset
|
|
||||||
#define SH1106_CMD_STARTLINE (uint8_t)0x40 // Set display start line
|
|
||||||
#define SH1106_CMD_SEG_NORM (uint8_t)0xA0 // Column 0 is mapped to SEG0 (X coordinate normal)
|
|
||||||
#define SH1106_CMD_SEG_INV (uint8_t)0xA1 // Column 127 is mapped to SEG0 (X coordinate inverted)
|
|
||||||
#define SH1106_CMD_COM_NORM (uint8_t)0xC0 // Scan from COM0 to COM[N-1] (N - mux ratio, Y coordinate normal)
|
|
||||||
#define SH1106_CMD_COM_INV (uint8_t)0xC8 // Scan from COM[N-1] to COM0 (N - mux ratio, Y coordinate inverted)
|
|
||||||
#define SH1106_CMD_COM_HW (uint8_t)0xDA // Set COM pins hardware configuration
|
|
||||||
#define SH1106_CMD_CONTRAST (uint8_t)0x81 // Contrast control
|
|
||||||
#define SH1106_CMD_EDON (uint8_t)0xA5 // Entire display ON enabled (all pixels on, RAM content ignored)
|
|
||||||
#define SH1106_CMD_EDOFF (uint8_t)0xA4 // Entire display ON disabled (output follows RAM content)
|
|
||||||
#define SH1106_CMD_INV_OFF (uint8_t)0xA6 // Entire display inversion OFF (normal display)
|
|
||||||
#define SH1106_CMD_INV_ON (uint8_t)0xA7 // Entire display inversion ON (all pixels inverted)
|
|
||||||
#define SH1106_CMD_CLOCKDIV (uint8_t)0xD5 // Set display clock divide ratio/oscillator frequency
|
|
||||||
#define SH1106_CMD_DISP_ON (uint8_t)0xAF // Display ON
|
|
||||||
#define SH1106_CMD_DISP_OFF (uint8_t)0xAE // Display OFF (sleep mode)
|
|
||||||
|
|
||||||
#define SH1106_CMD_COL_LOW (uint8_t)0x00 // Set Lower Column Address
|
using namespace stmlib;
|
||||||
#define SH1106_CMD_COL_HIGH (uint8_t)0x10 // Set Higher Column Address
|
|
||||||
#define SH1106_CMD_PAGE_ADDR (uint8_t)0xB0 // Set Page Address
|
|
||||||
|
|
||||||
#define SH1106_CMD_CHARGE (uint8_t)0x22 // Dis-charge / Pre-charge Period
|
const uint16_t kPinEnable = GPIO_Pin_2;
|
||||||
#define SH1106_CMD_SCRL_HR (uint8_t)0x26 // Setup continuous horizontal scroll right
|
const uint16_t kPinReset = GPIO_Pin_0;
|
||||||
#define SH1106_CMD_SCRL_HL (uint8_t)0x27 // Setup continuous horizontal scroll left
|
const uint16_t kPinDataCommand = GPIO_Pin_9;
|
||||||
#define SH1106_CMD_SCRL_VHR (uint8_t)0x29 // Setup continuous vertical and horizontal scroll right
|
|
||||||
#define SH1106_CMD_SCRL_VHL (uint8_t)0x2A // Setup continuous vertical and horizontal scroll left
|
u8g2_t u8g2_;
|
||||||
#define SH1106_CMD_SCRL_STOP (uint8_t)0x2E // Deactivate scroll
|
|
||||||
#define SH1106_CMD_SCRL_ACT (uint8_t)0x2F // Activate scroll
|
u8g2_t* Display::u8g2()
|
||||||
|
{
|
||||||
|
return &u8g2_;
|
||||||
|
}
|
||||||
|
|
||||||
void Display::Init()
|
void Display::Init()
|
||||||
{
|
{
|
||||||
gpio.Write(GPIO_PIN(SS_OLED), Bit_SET); // deactivate OLED spi
|
// init SS/CS/RST GPIO
|
||||||
|
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
|
||||||
gpio.Write(GPIO_PIN(RST_OLED), Bit_SET);
|
|
||||||
gpio.Write(GPIO_PIN(RST_OLED), Bit_RESET);
|
|
||||||
gpio.Write(GPIO_PIN(RST_OLED), Bit_SET);
|
|
||||||
|
|
||||||
GPIO_InitTypeDef gpio_init;
|
GPIO_InitTypeDef gpio_init;
|
||||||
gpio_init.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
|
gpio_init.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
|
gpio_init.GPIO_OType = GPIO_OType_PP;
|
||||||
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
|
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_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
|
||||||
SPI_InitTypeDef spi_init;
|
SPI_InitTypeDef spi_init;
|
||||||
spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||||
spi_init.SPI_Mode = SPI_Mode_Master;
|
spi_init.SPI_Mode = SPI_Mode_Master;
|
||||||
spi_init.SPI_DataSize = SPI_DataSize_8b;
|
spi_init.SPI_DataSize = SPI_DataSize_8b;
|
||||||
spi_init.SPI_CPOL = SPI_CPOL_Low;
|
spi_init.SPI_CPOL = SPI_CPOL_High;
|
||||||
spi_init.SPI_CPHA = SPI_CPHA_1Edge;
|
spi_init.SPI_CPHA = SPI_CPHA_2Edge;
|
||||||
spi_init.SPI_NSS = SPI_NSS_Soft;
|
spi_init.SPI_NSS = SPI_NSS_Soft;
|
||||||
spi_init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
|
spi_init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
|
||||||
spi_init.SPI_FirstBit = SPI_FirstBit_LSB;
|
spi_init.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||||
spi_init.SPI_CRCPolynomial = 10;
|
spi_init.SPI_CRCPolynomial = 7;
|
||||||
SPI_Init(SPI2, &spi_init);
|
SPI_Init(SPI2, &spi_init);
|
||||||
SPI_CalculateCRC(SPI2, DISABLE);
|
|
||||||
SPI_Cmd(SPI2, ENABLE);
|
SPI_Cmd(SPI2, ENABLE);
|
||||||
|
|
||||||
#define SH1106_cmd_double(x, y) \
|
GPIO_WriteBit(GPIOB, kPinReset, Bit_RESET);
|
||||||
WriteCommand(x); \
|
asm("nop");
|
||||||
WriteCommand(y);
|
|
||||||
#define SH1106_cmd(x) WriteCommand(x);
|
|
||||||
|
|
||||||
// Set multiplex ratio (visible lines)
|
GPIO_WriteBit(GPIOB, kPinReset, Bit_SET);
|
||||||
SH1106_cmd_double(SH1106_CMD_SETMUX, 0x3F); // 64MUX
|
InitGLib();
|
||||||
|
|
||||||
// Set display offset (offset of first line from the top of display)
|
|
||||||
SH1106_cmd_double(SH1106_CMD_SETOFFS, 0x00); // Offset: 0
|
|
||||||
|
|
||||||
// Set display start line (first line displayed)
|
|
||||||
SH1106_cmd(SH1106_CMD_STARTLINE | 0x00); // Start line: 0
|
|
||||||
|
|
||||||
// Set segment re-map (X coordinate)
|
|
||||||
SH1106_cmd(SH1106_CMD_SEG_NORM);
|
|
||||||
|
|
||||||
// Set COM output scan direction (Y coordinate)
|
|
||||||
SH1106_cmd(SH1106_CMD_COM_NORM);
|
|
||||||
|
|
||||||
// Set COM pins hardware configuration
|
|
||||||
// bit[4]: reset - sequential COM pin configuration
|
|
||||||
// set - alternative COM pin configuration (reset value)
|
|
||||||
// bit[5]: reset - disable COM left/right remap (reset value)
|
|
||||||
// set - enable COM left/right remap
|
|
||||||
SH1106_cmd_double(SH1106_CMD_COM_HW, 0x12);
|
|
||||||
|
|
||||||
uint8_t dis_charge = 0x00;
|
|
||||||
uint8_t pre_charge = 0x00;
|
|
||||||
|
|
||||||
SH1106_cmd_double(SH1106_CMD_CHARGE, dis_charge | (pre_charge << 4));
|
|
||||||
|
|
||||||
// Set contrast control
|
|
||||||
SH1106_cmd_double(SH1106_CMD_CONTRAST, 0x0F); // Contrast: middle level
|
|
||||||
|
|
||||||
SH1106_cmd(0x30);
|
|
||||||
|
|
||||||
// Disable entire display ON
|
|
||||||
SH1106_cmd(SH1106_CMD_EDOFF); // Display follows RAM content
|
|
||||||
|
|
||||||
// Disable display inversion
|
|
||||||
SH1106_cmd(SH1106_CMD_INV_OFF); // Normal display mode
|
|
||||||
|
|
||||||
// Set clock divide ratio and oscillator frequency
|
|
||||||
// bits[3:0] defines the divide ratio of the display clocks (bits[3:0] + 1)
|
|
||||||
// bits[7:4] set the oscillator frequency (Fosc), frequency increases with the value of these bits
|
|
||||||
// 0xF0 value gives maximum frequency (maximum Fosc without divider)
|
|
||||||
// 0x0F value gives minimum frequency (minimum Fosc divided by 16)
|
|
||||||
// The higher display frequency decreases image flickering but increases current consumption and vice versa
|
|
||||||
SH1106_cmd_double(SH1106_CMD_CLOCKDIV, 0xF0);
|
|
||||||
|
|
||||||
// Display ON
|
|
||||||
SH1106_cmd(SH1106_CMD_DISP_ON); // Display enabled
|
|
||||||
SH1106_cmd(SH1106_CMD_EDON);
|
|
||||||
Clear();
|
|
||||||
Update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::WriteCommand(uint8_t byte)
|
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)
|
||||||
{
|
{
|
||||||
gpio.Write(GPIO_PIN(SDC_OLED), Bit_RESET); // command mode
|
return 1;
|
||||||
gpio.Write(GPIO_PIN(SS_OLED), Bit_RESET); // activate OLED spi
|
|
||||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET)
|
|
||||||
;
|
|
||||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
|
|
||||||
;
|
|
||||||
SPI_I2S_SendData(SPI2, byte); // transmit via spi
|
|
||||||
gpio.Write(GPIO_PIN(SS_OLED), Bit_SET); // disable oled spi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::WriteData(uint8_t* buffer, uint8_t size)
|
uint8_t u8x8_byte_4wire_hw_spi(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int,
|
||||||
|
void* arg_ptr)
|
||||||
{
|
{
|
||||||
gpio.Write(GPIO_PIN(SDC_OLED), Bit_SET); // data mode
|
uint8_t* data;
|
||||||
gpio.Write(GPIO_PIN(SS_OLED), Bit_RESET); // activate OLED spi
|
switch (msg) {
|
||||||
for (int i = 0; i < size; i++) {
|
case U8X8_MSG_BYTE_SEND:
|
||||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET)
|
data = (uint8_t*)arg_ptr;
|
||||||
;
|
while (arg_int > 0) {
|
||||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
|
while (!(SPI2->SR & SPI_SR_TXE)) {
|
||||||
;
|
}
|
||||||
SPI_I2S_SendData(SPI2, buffer[i]); // transmit via spi
|
SPI_SendData8(SPI2, (uint8_t)*data);
|
||||||
for (int i = 0; i < 100; i++)
|
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:
|
||||||
|
GPIO_WriteBit(GPIOB, kPinEnable, Bit_RESET);
|
||||||
|
break;
|
||||||
|
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||||
|
GPIO_WriteBit(GPIOB, kPinEnable, Bit_SET);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
gpio.Write(GPIO_PIN(SS_OLED), Bit_SET); // disable oled spi
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::Clear()
|
void Display::InitGLib()
|
||||||
{
|
{
|
||||||
uint32_t i = 0;
|
u8g2_Setup_sh1106_128x64_noname_f(&u8g2_, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_stm32_gpio_and_delay);
|
||||||
for (i = 0; i < sizeof(buffer); i++)
|
u8g2_InitDisplay(&u8g2_);
|
||||||
buffer[i] = 0x00;
|
u8g2_SetContrast(&u8g2_, 127);
|
||||||
}
|
u8g2_SetPowerSave(&u8g2_, 0);
|
||||||
|
Random::Seed(42);
|
||||||
void Display::Update()
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < 8; i++) {
|
|
||||||
WriteCommand(0xb0 + i);
|
|
||||||
WriteCommand(0x00);
|
|
||||||
WriteCommand(0x10);
|
|
||||||
WriteData(&buffer[128 * i], 128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::WritePixel(uint8_t x, uint8_t y, bool color)
|
|
||||||
{
|
|
||||||
if (x > DISPLAY_WIDTH || y > DISPLAY_HEIGHT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (color) {
|
|
||||||
buffer[x + (y / 8) * DISPLAY_WIDTH] |= 1 << (y % 8);
|
|
||||||
} else {
|
|
||||||
buffer[x + (y / 8) * DISPLAY_WIDTH] &= ~(1 << (y % 8));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,7 @@
|
||||||
|
|
||||||
#include <stm32f37x_conf.h>
|
#include <stm32f37x_conf.h>
|
||||||
#include "stmlib/stmlib.h"
|
#include "stmlib/stmlib.h"
|
||||||
|
#include <u8g2.h>
|
||||||
#define DISPLAY_WIDTH 128
|
|
||||||
#define DISPLAY_HEIGHT 64
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Display {
|
class Display {
|
||||||
|
@ -15,15 +12,10 @@ class Display {
|
||||||
~Display() {}
|
~Display() {}
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void WritePixel(uint8_t x, uint8_t y, bool color);
|
u8g2_t* u8g2();
|
||||||
void Clear();
|
|
||||||
void Update();
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(Display);
|
DISALLOW_COPY_AND_ASSIGN(Display);
|
||||||
void WriteCommand(uint8_t byte);
|
void InitGLib();
|
||||||
void WriteData(uint8_t* data, uint8_t length);
|
|
||||||
|
|
||||||
uint8_t buffer[DISPLAY_WIDTH*DISPLAY_HEIGHT / 8];
|
|
||||||
};
|
};
|
||||||
|
extern Display display;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,24 +4,7 @@
|
||||||
|
|
||||||
|
|
||||||
void GPIO::Init() {
|
void GPIO::Init() {
|
||||||
GPIO_InitTypeDef gpio_init;
|
|
||||||
|
|
||||||
gpio_init.GPIO_Pin = PIN_RST_OLED | PIN_SS_DAC0 | PIN_SS_DAC1 | PIN_RST_USB | PIN_SS_USB | PIN_SS_OLED | PIN_SDC_OLED;
|
|
||||||
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
|
|
||||||
gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
||||||
GPIO_Init(GPIOB, &gpio_init);
|
|
||||||
|
|
||||||
gpio_init.GPIO_Pin = PIN_GATE_OUT_1 | PIN_GATE_OUT_2 | PIN_GATE_OUT_3 | PIN_GATE_OUT_4 | PIN_GATE_OUT_5 | PIN_GATE_OUT_6;
|
|
||||||
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
|
|
||||||
gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
||||||
GPIO_Init(GPIOA, &gpio_init);
|
|
||||||
|
|
||||||
Write(GPIO_PIN(SS_DAC0), Bit_SET);
|
|
||||||
Write(GPIO_PIN(SS_DAC1), Bit_SET);
|
|
||||||
Write(GPIO_PIN(SS_USB), Bit_SET);
|
|
||||||
Write(GPIO_PIN(SS_OLED), Bit_SET);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPIO::Write(GPIO_TypeDef* port, uint16_t pin, bool state) {
|
void GPIO::Write(GPIO_TypeDef* port, uint16_t pin, bool state) {
|
||||||
GPIO_WriteBit(port, pin, static_cast<BitAction>(state));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,15 @@
|
||||||
|
|
||||||
#include "drivers/display.h"
|
#include "drivers/display.h"
|
||||||
#include "drivers/gpio.h"
|
#include "drivers/gpio.h"
|
||||||
|
#include "stmlib/system/system_clock.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
using namespace stmlib;
|
using namespace stmlib;
|
||||||
|
|
||||||
GPIO gpio;
|
GPIO gpio;
|
||||||
Display display;
|
Display display;
|
||||||
|
UI ui;
|
||||||
|
//SystemClock system_clock;
|
||||||
|
|
||||||
// Default interrupt handlers.
|
// Default interrupt handlers.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -38,60 +42,76 @@ void PendSV_Handler() {}
|
||||||
// called every 1ms
|
// called every 1ms
|
||||||
void SysTick_Handler()
|
void SysTick_Handler()
|
||||||
{
|
{
|
||||||
}
|
IWDG_ReloadCounter();
|
||||||
|
system_clock.Tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(void)
|
void TIM2_IRQHandler(void)
|
||||||
{
|
{
|
||||||
SystemInit();
|
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == RESET) {
|
||||||
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x1000);
|
return;
|
||||||
|
}
|
||||||
|
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
||||||
|
|
||||||
|
// this will get called with 192 kHz (foof)
|
||||||
|
// we want to reduce the amount of times the ui gets polled to 1kHz
|
||||||
|
// which still is a lot (60fps would be enough tbh)
|
||||||
|
|
||||||
RCC_APB2PeriphClockCmd(
|
static uint8_t count = 0;
|
||||||
RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_TIM1 | RCC_APB2Periph_USART1, ENABLE);
|
count++;
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
|
if (count % 192 == 0) {
|
||||||
|
ui.Update();
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitTimers(void)
|
||||||
|
{
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||||
TIM_TimeBaseInitTypeDef timer_init;
|
TIM_TimeBaseInitTypeDef timer_init;
|
||||||
timer_init.TIM_Period = F_CPU / (48000 * 4) - 1;
|
timer_init.TIM_Period = F_CPU / (48000 * 4) - 1; // 192 kHz, 48kHz for each audio DAC
|
||||||
timer_init.TIM_Prescaler = 0;
|
timer_init.TIM_Prescaler = 0;
|
||||||
timer_init.TIM_ClockDivision = TIM_CKD_DIV1;
|
timer_init.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||||
timer_init.TIM_CounterMode = TIM_CounterMode_Up;
|
timer_init.TIM_CounterMode = TIM_CounterMode_Up;
|
||||||
timer_init.TIM_RepetitionCounter = 0;
|
timer_init.TIM_RepetitionCounter = 0;
|
||||||
TIM_InternalClockConfig(TIM1);
|
//TIM_InternalClockConfig(TIM2);
|
||||||
TIM_TimeBaseInit(TIM1, &timer_init);
|
TIM_TimeBaseInit(TIM2, &timer_init);
|
||||||
TIM_Cmd(TIM1, ENABLE);
|
TIM_Cmd(TIM2, ENABLE);
|
||||||
|
|
||||||
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 2.2 priority split.
|
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 2.2 priority split.
|
||||||
|
|
||||||
// DAC interrupt is given highest priority
|
// DAC interrupt is given highest priority
|
||||||
NVIC_InitTypeDef timer_interrupt;
|
NVIC_InitTypeDef timer_interrupt;
|
||||||
timer_interrupt.NVIC_IRQChannel = TIM1_UP_IRQn;
|
timer_interrupt.NVIC_IRQChannel = TIM2_IRQn;
|
||||||
timer_interrupt.NVIC_IRQChannelPreemptionPriority = 0;
|
timer_interrupt.NVIC_IRQChannelPreemptionPriority = 0;
|
||||||
timer_interrupt.NVIC_IRQChannelSubPriority = 0;
|
timer_interrupt.NVIC_IRQChannelSubPriority = 1;
|
||||||
timer_interrupt.NVIC_IRQChannelCmd = ENABLE;
|
timer_interrupt.NVIC_IRQChannelCmd = ENABLE;
|
||||||
NVIC_Init(&timer_interrupt);
|
NVIC_Init(&timer_interrupt);
|
||||||
|
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init(void)
|
||||||
|
{
|
||||||
|
//SystemInit();
|
||||||
|
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8000);
|
||||||
|
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
||||||
|
IWDG_SetPrescaler(IWDG_Prescaler_16);
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
|
||||||
|
|
||||||
|
system_clock.Init();
|
||||||
SysTick_Config(F_CPU / 8000);
|
SysTick_Config(F_CPU / 8000);
|
||||||
|
IWDG_Enable();
|
||||||
gpio.Init();
|
gpio.Init();
|
||||||
// asm("bkpt #0");
|
asm("bkpt #0");
|
||||||
display.Init();
|
display.Init();
|
||||||
|
InitTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
while (1) {
|
while (1) {
|
||||||
for (int x = 0; x < DISPLAY_WIDTH; x++)
|
//ui.Update();
|
||||||
for (int y = 0; y < DISPLAY_HEIGHT; y++) {
|
|
||||||
display.WritePixel(x, y, 0xff);
|
|
||||||
display.WritePixel(DISPLAY_WIDTH - x, DISPLAY_WIDTH - y, 0xff);
|
|
||||||
}
|
|
||||||
display.Update();
|
|
||||||
// hi
|
|
||||||
gpio.Write(GPIO_PIN(GATE_OUT_1), 0);
|
|
||||||
gpio.Write(GPIO_PIN(GATE_OUT_2), 0);
|
|
||||||
gpio.Write(GPIO_PIN(GATE_OUT_3), 0);
|
|
||||||
gpio.Write(GPIO_PIN(GATE_OUT_4), 0);
|
|
||||||
gpio.Write(GPIO_PIN(GATE_OUT_5), 0);
|
|
||||||
gpio.Write(GPIO_PIN(GATE_OUT_6), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
midi2cv/ui.cc
Normal file
31
midi2cv/ui.cc
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "ui.h"
|
||||||
|
#include "drivers/display.h"
|
||||||
|
#include "stmlib/utils/random.h"
|
||||||
|
#include <u8g2.h>
|
||||||
|
using namespace stmlib;
|
||||||
|
|
||||||
|
void UI::Update()
|
||||||
|
{
|
||||||
|
u8g2_t* u8g2_ = display.u8g2();
|
||||||
|
static float x = 0, y = 16, dx = 1, dy = 1, ddx = .2, ddy = .2;
|
||||||
|
u8g2_ClearBuffer(u8g2_);
|
||||||
|
u8g2_SetFont(u8g2_, u8g2_font_6x10_mf);
|
||||||
|
u8g2_DrawStr(u8g2_, (int)x, (int)y, "send nudes");
|
||||||
|
x += dx * ddx;
|
||||||
|
y += dy * ddy;
|
||||||
|
if (x >= 70 || x <= 0) {
|
||||||
|
ddx = Random::GetFloat() / 4.0 + 0.1;
|
||||||
|
}
|
||||||
|
if (x >= 70)
|
||||||
|
dx = -1;
|
||||||
|
if (x <= 0)
|
||||||
|
dx = 1;
|
||||||
|
if (y >= 64 || y <= 7) {
|
||||||
|
ddy = Random::GetFloat() / 4.0 + 0.1;
|
||||||
|
}
|
||||||
|
if (y >= 64)
|
||||||
|
dy = -1;
|
||||||
|
if (y <= 7)
|
||||||
|
dy = 1;
|
||||||
|
u8g2_SendBuffer(u8g2_);
|
||||||
|
}
|
19
midi2cv/ui.h
Normal file
19
midi2cv/ui.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef MIDI2CV_UI_H
|
||||||
|
#define MIDI2CV_UI_H
|
||||||
|
|
||||||
|
#include "stmlib/stmlib.h"
|
||||||
|
|
||||||
|
class UI {
|
||||||
|
public:
|
||||||
|
UI() {}
|
||||||
|
~UI() {}
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(UI);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern UI ui;
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue