mirror of
				https://github.com/jhbruhn/eurorack.git
				synced 2025-10-30 02:46:01 +00:00 
			
		
		
		
	Fix UI Drawing
This commit is contained in:
		
							parent
							
								
									91fd3e4302
								
							
						
					
					
						commit
						77d8c2d97e
					
				
					 3 changed files with 86 additions and 85 deletions
				
			
		|  | @ -1,10 +1,10 @@ | ||||||
| #include "display.h" | #include "display.h" | ||||||
| #include "gpio.h" | #include "gpio.h" | ||||||
|  | #include "spi_mode.h" | ||||||
| #include "stmlib/system/system_clock.h" | #include "stmlib/system/system_clock.h" | ||||||
| #include "stmlib/utils/random.h" | #include "stmlib/utils/random.h" | ||||||
| #include <stm32f37x_conf.h> | #include <stm32f37x_conf.h> | ||||||
| #include <u8g2.h> | #include <u8g2.h> | ||||||
| #include "spi_mode.h" |  | ||||||
| 
 | 
 | ||||||
| using namespace stmlib; | using namespace stmlib; | ||||||
| 
 | 
 | ||||||
|  | @ -19,119 +19,118 @@ uint8_t* output_buf; | ||||||
| 
 | 
 | ||||||
| u8g2_t* Display::u8g2() | u8g2_t* Display::u8g2() | ||||||
| { | { | ||||||
|     return &u8g2_; |   return &u8g2_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void InitSPI(void); | void InitSPI(void); | ||||||
| 
 | 
 | ||||||
| void Display::Init() | void Display::Init() | ||||||
| { | { | ||||||
|     // init SS/CS/RST GPIO
 |   // init SS/CS/RST GPIO
 | ||||||
|     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); |   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); | ||||||
| 
 | 
 | ||||||
|     GPIO_InitTypeDef gpio_init; |   GPIO_InitTypeDef gpio_init; | ||||||
|     gpio_init.GPIO_Mode = GPIO_Mode_OUT; |   gpio_init.GPIO_Mode = GPIO_Mode_OUT; | ||||||
|     gpio_init.GPIO_OType = GPIO_OType_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_PuPd = GPIO_PuPd_NOPULL; | ||||||
|     gpio_init.GPIO_Pin = kPinEnable | kPinReset | kPinDataCommand; |   gpio_init.GPIO_Pin = kPinEnable | kPinReset | kPinDataCommand; | ||||||
|     GPIO_Init(GPIOB, &gpio_init); |   GPIO_Init(GPIOB, &gpio_init); | ||||||
| 
 | 
 | ||||||
|     GPIO_WriteBit(GPIOB, kPinEnable, Bit_SET); |   GPIO_WriteBit(GPIOB, kPinEnable, Bit_SET); | ||||||
| 
 | 
 | ||||||
|     // init AF GPIO
 |   // init AF GPIO
 | ||||||
|     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); |   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); | ||||||
| 
 | 
 | ||||||
|     gpio_init.GPIO_Mode = GPIO_Mode_AF; |   gpio_init.GPIO_Mode = GPIO_Mode_AF; | ||||||
|     gpio_init.GPIO_OType = GPIO_OType_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_PuPd = GPIO_PuPd_NOPULL; | ||||||
|     gpio_init.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_14 | GPIO_Pin_15; |   gpio_init.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_14 | GPIO_Pin_15; | ||||||
|     GPIO_Init(GPIOB, &gpio_init); |   GPIO_Init(GPIOB, &gpio_init); | ||||||
|     GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_5); |   GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_5); | ||||||
|     GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_5); |   GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_5); | ||||||
|     GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_5); |   GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_5); | ||||||
| 
 | 
 | ||||||
|     // init SPI
 |   // init SPI
 | ||||||
|     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); |   RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); | ||||||
|     SPI_I2S_DeInit(SPI2); |   SPI_I2S_DeInit(SPI2); | ||||||
|     // Initialize SPI
 |   // Initialize SPI
 | ||||||
|     InitSPI(SPI_MODE_DISPLAY); |   InitSPI(SPI_MODE_DISPLAY); | ||||||
|     GPIO_WriteBit(GPIOB, kPinReset, Bit_RESET); |   GPIO_WriteBit(GPIOB, kPinReset, Bit_RESET); | ||||||
|     asm("nop"); |   asm("nop"); | ||||||
| 
 | 
 | ||||||
|     GPIO_WriteBit(GPIOB, kPinReset, Bit_SET); |   GPIO_WriteBit(GPIOB, kPinReset, Bit_SET); | ||||||
|     InitGLib(); |   InitGLib(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t* u8x8, | 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 uint8_t msg, U8X8_UNUSED uint8_t arg_int, | ||||||
|     U8X8_UNUSED void* arg_ptr) |     U8X8_UNUSED void* arg_ptr) | ||||||
| { | { | ||||||
|     return 1; |   return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t u8x8_byte_4wire_hw_spi(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, | uint8_t u8x8_byte_4wire_hw_spi(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, | ||||||
|     void* arg_ptr) |     void* arg_ptr) | ||||||
| { | { | ||||||
|     uint8_t* data; |   uint8_t* data; | ||||||
|     switch (msg) { |   switch (msg) { | ||||||
|     case U8X8_MSG_BYTE_SEND: |   case U8X8_MSG_BYTE_SEND: | ||||||
| 	data = (uint8_t*)arg_ptr; |     data = (uint8_t*)arg_ptr; | ||||||
| 	while (arg_int > 0) { |     while (arg_int > 0) { | ||||||
| 	    while (!(SPI2->SR & SPI_SR_TXE)) { |       while (!(SPI2->SR & SPI_SR_TXE)) { | ||||||
| 	    } |       } | ||||||
| 	    SPI_SendData8(SPI2, (uint8_t)*data); |       SPI_SendData8(SPI2, (uint8_t)*data); | ||||||
| 	    arg_int--; |       arg_int--; | ||||||
| 	    data++; |       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; |     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 Display::InitGLib() | void Display::InitGLib() | ||||||
| { | { | ||||||
|     u8g2_Setup_sh1106_128x64_noname_f(&u8g2_, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_stm32_gpio_and_delay); |   u8g2_Setup_sh1106_128x64_noname_f(&u8g2_, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_stm32_gpio_and_delay); | ||||||
|     output_buf = default_buf = u8g2_.tile_buf_ptr; |   output_buf = default_buf = u8g2_.tile_buf_ptr; | ||||||
|     u8g2_InitDisplay(&u8g2_); |   u8g2_InitDisplay(&u8g2_); | ||||||
|     u8g2_SetContrast(&u8g2_, 255); |   u8g2_SetContrast(&u8g2_, 255); | ||||||
|     u8g2_SetPowerSave(&u8g2_, 0); |   u8g2_SetPowerSave(&u8g2_, 0); | ||||||
| 
 | 
 | ||||||
|     Random::Seed(42); |   Random::Seed(42); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::Flush() | void Display::Flush() | ||||||
| { | { | ||||||
|     uint8_t* cache = u8g2_.tile_buf_ptr; |   uint8_t* cache = u8g2_.tile_buf_ptr; | ||||||
|     u8g2_.tile_buf_ptr = output_buf; |   u8g2_.tile_buf_ptr = output_buf; | ||||||
|     u8g2_SendBuffer(&u8g2_); |   u8g2_SendBuffer(&u8g2_); | ||||||
|     u8g2_.tile_buf_ptr = cache; |   u8g2_.tile_buf_ptr = cache; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::Swap() | void Display::Swap() | ||||||
| { | { | ||||||
|     output_buf = u8g2_.tile_buf_ptr; |   output_buf = u8g2_.tile_buf_ptr; | ||||||
|     if (output_buf == default_buf) |   if (output_buf == default_buf) | ||||||
| 	u8g2_.tile_buf_ptr = second_buf; |     u8g2_.tile_buf_ptr = second_buf; | ||||||
|     else |   else | ||||||
| 	u8g2_.tile_buf_ptr = default_buf; |     u8g2_.tile_buf_ptr = default_buf; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -56,12 +56,12 @@ void TIM2_IRQHandler(void) | ||||||
|   TIM_ClearITPendingBit(TIM2, TIM_IT_Update); |   TIM_ClearITPendingBit(TIM2, TIM_IT_Update); | ||||||
| 
 | 
 | ||||||
|   // this will get called with 192 kHz (foof)
 |   // this will get called with 192 kHz (foof)
 | ||||||
|   // we want to reduce the amount of times the ui gets polled to 1kHz
 |   // we want to reduce the amount of times the ui gets polled to 500 Hz
 | ||||||
|   // which still is a lot (60fps would be enough tbh)
 |   // which still is a lot (60fps would be enough tbh)
 | ||||||
| 
 | 
 | ||||||
|   static uint8_t count = 0; |   static uint8_t count = 0; | ||||||
|   count++; |   count++; | ||||||
|   if (count % 192 == 0) { |   if (count % (192 * 2) == 0) { | ||||||
|     ui.Flush(); |     ui.Flush(); | ||||||
|     count = 0; |     count = 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ const char part_names[4][2] = { "A", "B", "C", "D" }; | ||||||
| 
 | 
 | ||||||
| void UI::Update() | void UI::Update() | ||||||
| { | { | ||||||
| 
 |   u8g2_ClearBuffer(display.u8g2()); | ||||||
|   switch (current_menu) { |   switch (current_menu) { | ||||||
|   case MENU_PART_1: |   case MENU_PART_1: | ||||||
|   case MENU_PART_2: |   case MENU_PART_2: | ||||||
|  | @ -25,20 +25,22 @@ void UI::Update() | ||||||
| 
 | 
 | ||||||
|     break; |     break; | ||||||
|   } |   } | ||||||
|  |   display.Swap(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void UI::DrawHeader() | void UI::DrawHeader() | ||||||
| { | { | ||||||
|  |   u8g2_SetFont(display.u8g2(), u8g2_font_6x12_tf); | ||||||
|   for (int i = 0; i < PART_COUNT; i++) { |   for (int i = 0; i < PART_COUNT; i++) { | ||||||
|     u8g2_SetFontMode(display.u8g2(), 1); |     u8g2_SetFontMode(display.u8g2(), 1); | ||||||
|     u8g2_SetDrawColor(display.u8g2(), 1); |     u8g2_SetDrawColor(display.u8g2(), 1); | ||||||
|     if (current_menu == i) |     if (current_menu == i) | ||||||
|       u8g2_DrawBox(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT), 0, (DISPLAY_WIDTH / PART_COUNT), HEADER_HEIGHT); |       u8g2_DrawBox(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT), 0, (DISPLAY_WIDTH / PART_COUNT) - 1, HEADER_HEIGHT); | ||||||
|     else |     else | ||||||
|       u8g2_DrawFrame(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT), 0, (DISPLAY_WIDTH / PART_COUNT), HEADER_HEIGHT); |       u8g2_DrawFrame(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT), 0, (DISPLAY_WIDTH / PART_COUNT) - 1, HEADER_HEIGHT); | ||||||
| 
 | 
 | ||||||
|     u8g2_SetDrawColor(display.u8g2(), 2); |     u8g2_SetDrawColor(display.u8g2(), 2); | ||||||
|     u8g2_DrawStr(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT) + 2, 2, part_names[i]); |     u8g2_DrawStr(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT) + 5, 2 + 10, part_names[i]); | ||||||
|     u8g2_SetDrawColor(display.u8g2(), 1); |     u8g2_SetDrawColor(display.u8g2(), 1); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue