From b4bd41cd562f89bcd320ac0985e9b33c766babe1 Mon Sep 17 00:00:00 2001 From: JF Date: Sun, 19 Jan 2020 19:47:49 +0100 Subject: Implement the SPI driver using DMA. diff --git a/CMakeLists.txt b/CMakeLists.txt index 063decb..21c6379 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(pinetime VERSION 0.2.0 LANGUAGES C CXX ASM) +project(pinetime VERSION 0.2.99 LANGUAGES C CXX ASM) set(NRF_TARGET "nrf52") diff --git a/src/Components/Gfx/Gfx.cpp b/src/Components/Gfx/Gfx.cpp index 9e68068..6c19518 100644 --- a/src/Components/Gfx/Gfx.cpp +++ b/src/Components/Gfx/Gfx.cpp @@ -11,11 +11,21 @@ void Gfx::Init() { } void Gfx::ClearScreen() { - lcd.FillRectangle(0, 0, width, height, 0x0000); + SetBackgroundColor(0x0000); + lcd.BeginDrawBuffer(0, 0, width, height); + for(int i = 0; i < height; i++) { + lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); + } + lcd.EndDrawBuffer(); } void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint16_t color) { - lcd.FillRectangle(x, y, width, height, color); + SetBackgroundColor(color); + lcd.BeginDrawBuffer(0, 0, width, height); + for(int i = 0; i < height; i++) { + lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); + } + lcd.EndDrawBuffer(); } void Gfx::DrawString(uint8_t x, uint8_t y, uint16_t color, const char *text, const FONT_INFO *p_font, bool wrap) { @@ -70,15 +80,15 @@ void Gfx::DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint for (uint16_t i = 0; i < font->height; i++) { for (uint16_t j = 0; j < bytes_in_line; j++) { for (uint8_t k = 0; k < 8; k++) { - if ((1 << (7 - k)) & - font->data[font->charInfo[char_idx].offset + i * bytes_in_line + j]) { - lcd.NextDrawBuffer(reinterpret_cast(&color), 2); + if ((1 << (7 - k)) & font->data[font->charInfo[char_idx].offset + i * bytes_in_line + j]) { + buffer[(j*8)+k] = color; } else { - lcd.NextDrawBuffer(reinterpret_cast(&bg), 2); + buffer[(j*8)+k] = bg; } } } + lcd.NextDrawBuffer(reinterpret_cast(&buffer), bytes_in_line*8*2); } lcd.EndDrawBuffer(); *x += font->charInfo[char_idx].widthBits + font->spacePixels; @@ -96,4 +106,10 @@ void Gfx::Wakeup() { lcd.Wakeup(); } +void Gfx::SetBackgroundColor(uint16_t color) { + for(int i = 0; i < width; i++) { + buffer[i] = color; + } +} + diff --git a/src/Components/Gfx/Gfx.h b/src/Components/Gfx/Gfx.h index 9bd07fe..d872870 100644 --- a/src/Components/Gfx/Gfx.h +++ b/src/Components/Gfx/Gfx.h @@ -21,10 +21,14 @@ namespace Pinetime { void Wakeup(); private: + static constexpr uint8_t width = 240; + static constexpr uint8_t height = 240; + + uint16_t buffer[width]; // 1 line buffer Drivers::St7789& lcd; - const uint8_t width = 240; - const uint8_t height = 240; + void pixel_draw(uint8_t x, uint8_t y, uint16_t color); + void SetBackgroundColor(uint16_t color); }; } } diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index 3b7007a..29c75fa 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -31,8 +31,8 @@ DisplayApp::DisplayApp(Controllers::Battery &batteryController, batteryController{batteryController}, bleController{bleController}, dateTimeController{dateTimeController}, - clockScreen{*(gfx.get())}/*, - messageScreen{*(gfx.get())}*/ { + clockScreen{*(gfx.get())}, + messageScreen{*(gfx.get())} { msgQueue = xQueueCreate(queueSize, itemSize); currentScreen = &clockScreen; } @@ -121,16 +121,20 @@ void DisplayApp::Refresh() { void DisplayApp::RunningState() { clockScreen.SetCurrentDateTime(dateTimeController.CurrentDateTime()); +// if(currentScreen != nullptr) { +// currentScreen->Refresh(false); +// } + if(currentScreen != nullptr) { - currentScreen->Refresh(false); + currentScreen->Refresh(true); } -// if(screenState) { -// currentScreen = &clockScreen; -// } else { -// currentScreen = &messageScreen; -// } -// screenState = !screenState; + if(screenState) { + currentScreen = &clockScreen; + } else { + currentScreen = &messageScreen; + } + screenState = !screenState; } @@ -153,7 +157,7 @@ void DisplayApp::OnTouchEvent() { auto info = touchPanel.GetTouchInfo(); if(info.isTouch) { - lcd->FillRectangle(info.x-10, info.y-10, 20,20, pointColor); + gfx->FillRectangle(info.x-10, info.y-10, 20,20, pointColor); pointColor+=10; } } diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h index 5fb8f6f..eabfe09 100644 --- a/src/DisplayApp/DisplayApp.h +++ b/src/DisplayApp/DisplayApp.h @@ -57,8 +57,8 @@ namespace Pinetime { Screens::Clock clockScreen; Screens::Screen* currentScreen = nullptr; -// Screens::Message messageScreen; -// bool screenState = false; + Screens::Message messageScreen; + bool screenState = false; static constexpr uint8_t pinSpiSck = 2; static constexpr uint8_t pinSpiMosi = 3; static constexpr uint8_t pinSpiMiso = 4; diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 42d3d77..e8130c7 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -1,6 +1,7 @@ #include +#include #include "SpiMaster.h" - +#include using namespace Pinetime::Drivers; SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters ¶ms) : @@ -9,22 +10,24 @@ SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters bool SpiMaster::Init() { /* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */ + nrf_gpio_pin_set(params.pinSCK); nrf_gpio_cfg_output(params.pinSCK); + nrf_gpio_pin_clear(params.pinMOSI); nrf_gpio_cfg_output(params.pinMOSI); nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_output(params.pinCSN); pinCsn = params.pinCSN; switch(spi) { - case SpiModule::SPI0: spiBaseAddress = NRF_SPI0; break; - case SpiModule::SPI1: spiBaseAddress = NRF_SPI1; break; + case SpiModule::SPI0: spiBaseAddress = NRF_SPIM0; break; + case SpiModule::SPI1: spiBaseAddress = NRF_SPIM1; break; default: return false; } /* Configure pins, frequency and mode */ - spiBaseAddress->PSELSCK = params.pinSCK; - spiBaseAddress->PSELMOSI = params.pinMOSI; - spiBaseAddress->PSELMISO = params.pinMISO; + NRF_SPIM0->PSELSCK = params.pinSCK; + NRF_SPIM0->PSELMOSI = params.pinMOSI; + NRF_SPIM0->PSELMISO = params.pinMISO; nrf_gpio_pin_set(pinCsn); /* disable Set slave select (inactive high) */ uint32_t frequency; @@ -32,7 +35,7 @@ bool SpiMaster::Init() { case Frequencies::Freq8Mhz: frequency = 0x80000000; break; default: return false; } - spiBaseAddress->FREQUENCY = frequency; + NRF_SPIM0->FREQUENCY = frequency; uint32_t regConfig = 0; switch(params.bitOrder) { @@ -48,14 +51,21 @@ bool SpiMaster::Init() { default: return false; } - spiBaseAddress->CONFIG = regConfig; - spiBaseAddress->EVENTS_READY = 0; - spiBaseAddress->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); + setup_workaround_for_ftpan_58(NRF_SPIM0, 0, 0); + + NRF_SPIM0->CONFIG = regConfig; + NRF_SPIM0->EVENTS_ENDRX = 0; + NRF_SPIM0->EVENTS_ENDTX = 0; + NRF_SPIM0->EVENTS_END = 0; + NRF_SPI0->EVENTS_READY = 0; + NRF_SPI0->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); + NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); return true; } -bool SpiMaster::Write(const uint8_t *data, size_t size) { +bool SpiMaster::WriteFast(const uint8_t *data, size_t size) { + auto spi = reinterpret_cast(spiBaseAddress); volatile uint32_t dummyread; if(data == nullptr) return false; @@ -63,27 +73,27 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { /* enable slave (slave select active low) */ nrf_gpio_pin_clear(pinCsn); - spiBaseAddress->EVENTS_READY = 0; + NRF_SPI0->EVENTS_READY = 0; - spiBaseAddress->TXD = (uint32_t)*data++; + NRF_SPI0->TXD = (uint32_t)*data++; while(--size) { - spiBaseAddress->TXD = (uint32_t)*data++; + NRF_SPI0->TXD = (uint32_t)*data++; /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ - while (spiBaseAddress->EVENTS_READY == 0); + while (NRF_SPI0->EVENTS_READY == 0); /* clear the event to be ready to receive next messages */ - spiBaseAddress->EVENTS_READY = 0; + NRF_SPI0->EVENTS_READY = 0; - dummyread = spiBaseAddress->RXD; + dummyread = NRF_SPI0->RXD; } /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ - while (spiBaseAddress->EVENTS_READY == 0); + while (NRF_SPI0->EVENTS_READY == 0); - dummyread = spiBaseAddress->RXD; + dummyread = NRF_SPI0->RXD; /* disable slave (slave select active low) */ nrf_gpio_pin_set(pinCsn); @@ -91,9 +101,68 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { return true; } +void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel) { + // Create an event when SCK toggles. + NRF_GPIOTE->CONFIG[gpiote_channel] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | + (spim->PSEL.SCK << GPIOTE_CONFIG_PSEL_Pos) | + (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos); + + // Stop the spim instance when SCK toggles. + NRF_PPI->CH[ppi_channel].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[gpiote_channel]; + NRF_PPI->CH[ppi_channel].TEP = (uint32_t) &spim->TASKS_STOP; + NRF_PPI->CHENSET = 1U << ppi_channel; +} + +bool SpiMaster::Write(const uint8_t *data, size_t size) { + if(data == nullptr) return false; + + if(size == 1) { + setup_workaround_for_ftpan_58(NRF_SPIM0, 0,0); + } else { + NRF_GPIOTE->CONFIG[0] = 0; + NRF_PPI->CH[0].EEP = 0; + NRF_PPI->CH[0].TEP = 0; + NRF_PPI->CHENSET = 0; + } + + nrf_gpio_pin_clear(pinCsn); + auto spim = reinterpret_cast(spiBaseAddress); + + while(size > 0) { + auto currentSize = std::min((size_t)255, size); + size -= currentSize; + NRF_SPIM0->TXD.PTR = (uint32_t) data; + NRF_SPIM0->TXD.MAXCNT = currentSize; + NRF_SPIM0->TXD.LIST = 0; + + NRF_SPIM0->RXD.PTR = (uint32_t) 0; + NRF_SPIM0->RXD.MAXCNT = 0; + NRF_SPIM0->RXD.LIST = 0; + + NRF_SPIM0->EVENTS_END = 0; + + NRF_SPIM0->TASKS_START = 1; + + + while (NRF_SPIM0->EVENTS_END == 0); + } + + nrf_gpio_pin_set(pinCsn); + + return true; +} + +bool SpiMaster::GetStatusEnd() { + return (bool)*(volatile uint32_t *)((uint8_t *)spiBaseAddress + (uint32_t)NRF_SPIM_EVENT_END); +} + +bool SpiMaster::GetStatusStarted() { + return (bool)*(volatile uint32_t *)((uint8_t *)spiBaseAddress + (uint32_t)NRF_SPIM_EVENT_STARTED); +} + void SpiMaster::Sleep() { - while(NRF_SPI0->ENABLE != 0) { - NRF_SPI0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); + while(NRF_SPIM0->ENABLE != 0) { + NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); } nrf_gpio_cfg_default(params.pinSCK); nrf_gpio_cfg_default(params.pinMOSI); diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 073501a..5376ac8 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -24,12 +24,17 @@ namespace Pinetime { SpiMaster(const SpiModule spi, const Parameters& params); bool Init(); bool Write(const uint8_t* data, size_t size); + bool WriteFast(const uint8_t* data, size_t size); + void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); void Sleep(); void Wakeup(); + bool GetStatusEnd(); + bool GetStatusStarted(); + private: - NRF_SPI_Type * spiBaseAddress; + NRF_SPIM_Type * spiBaseAddress; uint8_t pinCsn; SpiMaster::SpiModule spi; diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index ac81306..f47c2f5 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -38,7 +38,7 @@ void St7789::WriteData(uint8_t data) { void St7789::WriteSpi(const uint8_t* data, size_t size) { - spi.Write(data, size); + spi.Write(data, size); } void St7789::SoftwareReset() { @@ -95,20 +95,6 @@ void St7789::DisplayOn() { WriteCommand(static_cast(Commands::DisplayOn)); } -void St7789::FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) { - BeginDrawBuffer(x, y, width, height); - - uint32_t c = color + (color << 16); - uint8_t w = width/2; - - for(y=height+ST7789_ROW_OFFSET; y>ST7789_ROW_OFFSET; y--) { - for(x=w; x>0; x--) { - NextDrawBuffer(reinterpret_cast(&c), 4); - } - } - EndDrawBuffer(); -} - void St7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { WriteCommand(static_cast(Commands::ColumnAddressSet)); WriteData(x0 >> 8); @@ -160,7 +146,7 @@ void St7789::EndDrawBuffer() { } void St7789::NextDrawBuffer(const uint8_t *data, size_t size) { - spi.Write(data, size); + WriteSpi(data, size); } void St7789::HardwareReset() { diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index a32a96f..8e4690b 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -10,7 +10,6 @@ namespace Pinetime { void Init(); void Uninit(); void DrawPixel(uint16_t x, uint16_t y, uint32_t color); - void FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color); void BeginDrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height); void NextDrawBuffer(const uint8_t* data, size_t size); -- cgit v0.10.2 From aa3e5c0c6f6f7bb9df02ae5d333dc6c4a6d2e744 Mon Sep 17 00:00:00 2001 From: JF Date: Wed, 22 Jan 2020 19:45:53 +0100 Subject: [WIP] Use IRQ in SPI driver to improve performances diff --git a/src/DisplayApp/Screens/Clock.cpp b/src/DisplayApp/Screens/Clock.cpp index 153f4f2..155cb58 100644 --- a/src/DisplayApp/Screens/Clock.cpp +++ b/src/DisplayApp/Screens/Clock.cpp @@ -9,10 +9,10 @@ using namespace Pinetime::Applications::Screens; void Clock::Refresh(bool fullRefresh) { if(fullRefresh) { gfx.FillRectangle(0,0,240,240,0x0000); - currentChar[0] = 0; - currentChar[1] = 0; - currentChar[2] = 0; - currentChar[3] = 0; + currentChar[0] = 1; + currentChar[1] = 2; + currentChar[2] = 3; + currentChar[3] = 4; auto dummy = currentDateTime.Get(); } diff --git a/src/DisplayApp/Screens/Message.cpp b/src/DisplayApp/Screens/Message.cpp index 2ade434..121e34b 100644 --- a/src/DisplayApp/Screens/Message.cpp +++ b/src/DisplayApp/Screens/Message.cpp @@ -9,6 +9,6 @@ using namespace Pinetime::Applications::Screens; void Message::Refresh(bool fullRefresh) { if(fullRefresh) { gfx.FillRectangle(0,0,240,240,0xffff); - gfx.DrawString(120, 10, 0x0000, "COUCOU", &smallFont, false); + gfx.DrawString(120, 10, 0x5555, "COUCOU", &smallFont, false); } } diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index e8130c7..f7e64db 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -4,8 +4,10 @@ #include using namespace Pinetime::Drivers; +SpiMaster* spiInstance; SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters ¶ms) : spi{spi}, params{params} { + spiInstance = this; } bool SpiMaster::Init() { @@ -57,50 +59,18 @@ bool SpiMaster::Init() { NRF_SPIM0->EVENTS_ENDRX = 0; NRF_SPIM0->EVENTS_ENDTX = 0; NRF_SPIM0->EVENTS_END = 0; - NRF_SPI0->EVENTS_READY = 0; - NRF_SPI0->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); - NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); - - return true; -} - -bool SpiMaster::WriteFast(const uint8_t *data, size_t size) { - auto spi = reinterpret_cast(spiBaseAddress); - volatile uint32_t dummyread; - - if(data == nullptr) return false; - - /* enable slave (slave select active low) */ - nrf_gpio_pin_clear(pinCsn); - NRF_SPI0->EVENTS_READY = 0; + NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)6); + NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)1); - NRF_SPI0->TXD = (uint32_t)*data++; - - while(--size) - { - NRF_SPI0->TXD = (uint32_t)*data++; - - /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ - while (NRF_SPI0->EVENTS_READY == 0); - - /* clear the event to be ready to receive next messages */ - NRF_SPI0->EVENTS_READY = 0; - - dummyread = NRF_SPI0->RXD; - } - - /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ - while (NRF_SPI0->EVENTS_READY == 0); - - dummyread = NRF_SPI0->RXD; - - /* disable slave (slave select active low) */ - nrf_gpio_pin_set(pinCsn); + NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); + NRFX_IRQ_PRIORITY_SET(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn,6); + NRFX_IRQ_ENABLE(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn); return true; } + void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel) { // Create an event when SCK toggles. NRF_GPIOTE->CONFIG[gpiote_channel] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | @@ -113,41 +83,85 @@ void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_ NRF_PPI->CHENSET = 1U << ppi_channel; } + + +void SpiMaster::irq() { + if(busy) { + if(bufferSize > 0) { + auto currentSize = std::min((size_t)255, bufferSize); + + NRF_SPIM0->TXD.PTR = (uint32_t) bufferAddr; + NRF_SPIM0->TXD.MAXCNT = currentSize; + NRF_SPIM0->TXD.LIST = 0; + + bufferAddr += currentSize; + bufferSize -= currentSize; + + NRF_SPIM0->RXD.PTR = (uint32_t) 0; + NRF_SPIM0->RXD.MAXCNT = 0; + NRF_SPIM0->RXD.LIST = 0; + NRF_SPIM0->TASKS_START = 1; + + return; + }else { + nrf_gpio_pin_set(pinCsn); + busy = false; + } + } +} + bool SpiMaster::Write(const uint8_t *data, size_t size) { if(data == nullptr) return false; + while(busy) { + asm("nop"); + } + if(size == 1) { setup_workaround_for_ftpan_58(NRF_SPIM0, 0,0); + NRF_SPIM0->INTENCLR = (1<<6); + NRF_SPIM0->INTENCLR = (1<<1); + } else { NRF_GPIOTE->CONFIG[0] = 0; NRF_PPI->CH[0].EEP = 0; NRF_PPI->CH[0].TEP = 0; NRF_PPI->CHENSET = 0; + NRF_SPIM0->INTENSET = (1<<6); + NRF_SPIM0->INTENSET = (1<<1); } nrf_gpio_pin_clear(pinCsn); - auto spim = reinterpret_cast(spiBaseAddress); - while(size > 0) { - auto currentSize = std::min((size_t)255, size); - size -= currentSize; + bufferAddr = (uint32_t)data; + bufferSize = size; + busy = true; + +// while(size > 0) { + auto currentSize = std::min((size_t)255, bufferSize); NRF_SPIM0->TXD.PTR = (uint32_t) data; NRF_SPIM0->TXD.MAXCNT = currentSize; NRF_SPIM0->TXD.LIST = 0; + bufferSize -= currentSize; + bufferAddr += currentSize; + NRF_SPIM0->RXD.PTR = (uint32_t) 0; NRF_SPIM0->RXD.MAXCNT = 0; NRF_SPIM0->RXD.LIST = 0; - NRF_SPIM0->EVENTS_END = 0; + if(size != 1) { + NRF_SPIM0->EVENTS_END = 0; + } NRF_SPIM0->TASKS_START = 1; + if(size == 1) { + while (NRF_SPIM0->EVENTS_END == 0); + busy = false; + nrf_gpio_pin_set(pinCsn); + } - while (NRF_SPIM0->EVENTS_END == 0); - } - - nrf_gpio_pin_set(pinCsn); return true; } diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 5376ac8..dff63e9 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -2,7 +2,7 @@ #include #include #include - +#include namespace Pinetime { namespace Drivers { class SpiMaster { @@ -24,7 +24,7 @@ namespace Pinetime { SpiMaster(const SpiModule spi, const Parameters& params); bool Init(); bool Write(const uint8_t* data, size_t size); - bool WriteFast(const uint8_t* data, size_t size); + bool WriteRepeat(const uint8_t *data, size_t size, int repeat); void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); void Sleep(); @@ -33,12 +33,20 @@ namespace Pinetime { bool GetStatusEnd(); bool GetStatusStarted(); + void irq(); + private: NRF_SPIM_Type * spiBaseAddress; uint8_t pinCsn; SpiMaster::SpiModule spi; SpiMaster::Parameters params; + + std::atomic busy {false}; + + uint32_t bufferAddr = 0; + + size_t bufferSize = 0; }; } } diff --git a/src/main.cpp b/src/main.cpp index 062a36e..14be5ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -158,6 +158,20 @@ void OnNewTime(current_time_char_t* currentTime) { dayOfWeek, hour, minute, second, nrf_rtc_counter_get(portNRF_RTC_REG)); } +extern Pinetime::Drivers::SpiMaster* spiInstance; +void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) { + if(((NRF_SPIM0->INTENSET & (1<<6)) != 0) && NRF_SPIM0->EVENTS_END == 1) { + NRF_SPIM0->EVENTS_END = 0; + spiInstance->irq(); + } + + + if(((NRF_SPIM0->INTENSET & (1<<1)) != 0) && NRF_SPIM0->EVENTS_STOPPED == 1) { + NRF_SPIM0->EVENTS_STOPPED = 0; + } + + return; +} int main(void) { displayApp.reset(new Pinetime::Applications::DisplayApp(batteryController, bleController, dateTimeController)); logger.Init(); -- cgit v0.10.2 From eb7a1b3ac9cbacb74afb7fcd1d40c51a18c90060 Mon Sep 17 00:00:00 2001 From: JF Date: Wed, 22 Jan 2020 21:08:53 +0100 Subject: [WIP] Max SPI speed reached (119ms for a full refresh. Theo max : 240*240*16 = 115.2ms) using IRQ and DMA. Code needs some cleaning before integration. diff --git a/src/Components/Gfx/Gfx.cpp b/src/Components/Gfx/Gfx.cpp index 6c19518..9410651 100644 --- a/src/Components/Gfx/Gfx.cpp +++ b/src/Components/Gfx/Gfx.cpp @@ -22,9 +22,7 @@ void Gfx::ClearScreen() { void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint16_t color) { SetBackgroundColor(color); lcd.BeginDrawBuffer(0, 0, width, height); - for(int i = 0; i < height; i++) { - lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); - } + lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2, 240); lcd.EndDrawBuffer(); } diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index 29c75fa..c1561cc 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -65,7 +65,28 @@ void DisplayApp::InitHw() { touchPanel.Init(); } +uint32_t acc = 0; +uint32_t count = 0; +bool toggle = true; void DisplayApp::Refresh() { + + uint32_t before = nrf_rtc_counter_get(portNRF_RTC_REG); + if(toggle) { + gfx->FillRectangle(0,0,240,240,0x0000); + } else { + gfx->FillRectangle(0,0,240,240,0xffff); + } + uint32_t after = nrf_rtc_counter_get(portNRF_RTC_REG); + + acc += (after - before); + if((count % 10) == 0) { + NRF_LOG_INFO("DRAW : %d ms", (uint32_t)(acc/10)); + acc = 0; + } + count++; + toggle = !toggle; + +#if 0 TickType_t queueTimeout; switch (state) { case States::Idle: @@ -116,6 +137,7 @@ void DisplayApp::Refresh() { break; } } +#endif } void DisplayApp::RunningState() { diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index f7e64db..7c6186a 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -62,6 +62,7 @@ bool SpiMaster::Init() { NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)6); NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)1); + NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)19); NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); @@ -83,34 +84,61 @@ void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_ NRF_PPI->CHENSET = 1U << ppi_channel; } - - -void SpiMaster::irq() { +void SpiMaster::irqStarted() { if(busy) { - if(bufferSize > 0) { - auto currentSize = std::min((size_t)255, bufferSize); + auto s = currentBufferSize; + if(s > 0) { + auto currentSize = std::min((size_t)255, s); - NRF_SPIM0->TXD.PTR = (uint32_t) bufferAddr; + NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; NRF_SPIM0->TXD.MAXCNT = currentSize; NRF_SPIM0->TXD.LIST = 0; - bufferAddr += currentSize; - bufferSize -= currentSize; + currentBufferAddr += currentSize; + currentBufferSize -= currentSize; NRF_SPIM0->RXD.PTR = (uint32_t) 0; NRF_SPIM0->RXD.MAXCNT = 0; NRF_SPIM0->RXD.LIST = 0; - NRF_SPIM0->TASKS_START = 1; + + if(repeat == 0) + NRF_SPIM0->SHORTS = 0; return; }else { + if(repeat > 0) { + repeat = repeat -1; + + currentBufferAddr = bufferAddr; + currentBufferSize = bufferSize; + s = currentBufferSize; + auto currentSize = std::min((size_t)255, s); + NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; + NRF_SPIM0->TXD.MAXCNT = currentSize; + NRF_SPIM0->TXD.LIST = 0; + + currentBufferAddr += currentSize; + currentBufferSize -= currentSize; + + NRF_SPIM0->RXD.PTR = (uint32_t) 0; + NRF_SPIM0->RXD.MAXCNT = 0; + NRF_SPIM0->RXD.LIST = 0; + } + } + } +} + +void SpiMaster::irqEnd() { + if(busy) { + if(repeat == 0 && currentBufferSize == 0) { nrf_gpio_pin_set(pinCsn); busy = false; } } } -bool SpiMaster::Write(const uint8_t *data, size_t size) { + +bool SpiMaster::Write(const uint8_t *data, size_t size, size_t r) { if(data == nullptr) return false; while(busy) { @@ -121,7 +149,7 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { setup_workaround_for_ftpan_58(NRF_SPIM0, 0,0); NRF_SPIM0->INTENCLR = (1<<6); NRF_SPIM0->INTENCLR = (1<<1); - + NRF_SPIM0->INTENCLR = (1<<19); } else { NRF_GPIOTE->CONFIG[0] = 0; NRF_PPI->CH[0].EEP = 0; @@ -129,38 +157,38 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { NRF_PPI->CHENSET = 0; NRF_SPIM0->INTENSET = (1<<6); NRF_SPIM0->INTENSET = (1<<1); + NRF_SPIM0->INTENSET = (1<<19); } nrf_gpio_pin_clear(pinCsn); - bufferAddr = (uint32_t)data; - bufferSize = size; + currentBufferAddr = bufferAddr = (uint32_t)data; + currentBufferSize = bufferSize = size; + repeat = r; busy = true; -// while(size > 0) { - auto currentSize = std::min((size_t)255, bufferSize); - NRF_SPIM0->TXD.PTR = (uint32_t) data; - NRF_SPIM0->TXD.MAXCNT = currentSize; - NRF_SPIM0->TXD.LIST = 0; - - bufferSize -= currentSize; - bufferAddr += currentSize; + if(repeat > 0) + NRF_SPIM0->SHORTS = (1<<17); - NRF_SPIM0->RXD.PTR = (uint32_t) 0; - NRF_SPIM0->RXD.MAXCNT = 0; - NRF_SPIM0->RXD.LIST = 0; + auto currentSize = std::min((size_t)255, bufferSize); + NRF_SPIM0->TXD.PTR = bufferAddr; + NRF_SPIM0->TXD.MAXCNT = currentSize; + NRF_SPIM0->TXD.LIST = 0; - if(size != 1) { - NRF_SPIM0->EVENTS_END = 0; - } + currentBufferSize -= currentSize; + currentBufferAddr += currentSize; - NRF_SPIM0->TASKS_START = 1; + NRF_SPIM0->RXD.PTR = (uint32_t) 0; + NRF_SPIM0->RXD.MAXCNT = 0; + NRF_SPIM0->RXD.LIST = 0; + NRF_SPIM0->EVENTS_END = 0; + NRF_SPIM0->TASKS_START = 1; - if(size == 1) { - while (NRF_SPIM0->EVENTS_END == 0); - busy = false; - nrf_gpio_pin_set(pinCsn); - } + if(size == 1) { + while (NRF_SPIM0->EVENTS_END == 0); + busy = false; + nrf_gpio_pin_set(pinCsn); + } return true; @@ -187,3 +215,9 @@ void SpiMaster::Sleep() { void SpiMaster::Wakeup() { Init(); } + +void SpiMaster::Wait() { + while(busy) { + asm("nop"); + } +} diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index dff63e9..ee03186 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -23,9 +23,9 @@ namespace Pinetime { SpiMaster(const SpiModule spi, const Parameters& params); bool Init(); - bool Write(const uint8_t* data, size_t size); - bool WriteRepeat(const uint8_t *data, size_t size, int repeat); + bool Write(const uint8_t* data, size_t size, size_t r = 0); void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); + void Wait(); void Sleep(); void Wakeup(); @@ -33,7 +33,8 @@ namespace Pinetime { bool GetStatusEnd(); bool GetStatusStarted(); - void irq(); + void irqEnd(); + void irqStarted(); private: NRF_SPIM_Type * spiBaseAddress; @@ -42,11 +43,13 @@ namespace Pinetime { SpiMaster::SpiModule spi; SpiMaster::Parameters params; - std::atomic busy {false}; + volatile bool busy = false; uint32_t bufferAddr = 0; - + volatile uint32_t currentBufferAddr = 0; size_t bufferSize = 0; + volatile size_t currentBufferSize = 0; + volatile uint32_t repeat = 0; }; } } diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index f47c2f5..6b66313 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -37,8 +37,8 @@ void St7789::WriteData(uint8_t data) { } -void St7789::WriteSpi(const uint8_t* data, size_t size) { - spi.Write(data, size); +void St7789::WriteSpi(const uint8_t* data, size_t size, size_t repeat) { + spi.Write(data, size, repeat); } void St7789::SoftwareReset() { @@ -143,10 +143,11 @@ void St7789::BeginDrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t he } void St7789::EndDrawBuffer() { + spi.Wait(); } -void St7789::NextDrawBuffer(const uint8_t *data, size_t size) { - WriteSpi(data, size); +void St7789::NextDrawBuffer(const uint8_t *data, size_t size, size_t repeat) { + WriteSpi(data, size, repeat); } void St7789::HardwareReset() { diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index 8e4690b..eef051b 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -12,7 +12,7 @@ namespace Pinetime { void DrawPixel(uint16_t x, uint16_t y, uint32_t color); void BeginDrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height); - void NextDrawBuffer(const uint8_t* data, size_t size); + void NextDrawBuffer(const uint8_t* data, size_t size, size_t repeat = 0); void EndDrawBuffer(); void DisplayOn(); @@ -40,7 +40,7 @@ namespace Pinetime { void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void WriteCommand(uint8_t cmd); - void WriteSpi(const uint8_t* data, size_t size); + void WriteSpi(const uint8_t* data, size_t size, size_t repeat = 0); enum class Commands : uint8_t { SoftwareReset = 0x01, diff --git a/src/main.cpp b/src/main.cpp index 14be5ca..284113c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -162,7 +162,12 @@ extern Pinetime::Drivers::SpiMaster* spiInstance; void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) { if(((NRF_SPIM0->INTENSET & (1<<6)) != 0) && NRF_SPIM0->EVENTS_END == 1) { NRF_SPIM0->EVENTS_END = 0; - spiInstance->irq(); + spiInstance->irqEnd(); + } + + if(((NRF_SPIM0->INTENSET & (1<<19)) != 0) && NRF_SPIM0->EVENTS_STARTED == 1) { + NRF_SPIM0->EVENTS_STARTED = 0; + spiInstance->irqStarted(); } diff --git a/src/sdk_config.h b/src/sdk_config.h index 2136320..e74751e 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -8452,15 +8452,15 @@ // NRF_LOG_ENABLED - nrf_log - Logger //========================================================== #ifndef NRF_LOG_ENABLED -#define NRF_LOG_ENABLED 0 +#define NRF_LOG_ENABLED 1 #endif #ifndef NRF_LOG_BACKEND_RTT_ENABLED -#define NRF_LOG_BACKEND_RTT_ENABLED 0 +#define NRF_LOG_BACKEND_RTT_ENABLED 1 #endif #ifndef NRF_LOG_BACKEND_SERIAL_USES_RTT -#define NRF_LOG_BACKEND_SERIAL_USES_RTT 0 +#define NRF_LOG_BACKEND_SERIAL_USES_RTT 1 #endif // Log message pool - Configuration of log message pool -- cgit v0.10.2 From 5fa4f5abe0b752bb2d990378e02d6424a1d1b661 Mon Sep 17 00:00:00 2001 From: JF Date: Sun, 26 Jan 2020 13:37:10 +0100 Subject: Better integration of SPI with DMA and IRQ. Using only 'End' IRQ. Perf could be improved by using 'Started' IRQ to prepare the next buffer while the current one is beeing sent. diff --git a/src/Components/Gfx/Gfx.cpp b/src/Components/Gfx/Gfx.cpp index 9410651..2f64596 100644 --- a/src/Components/Gfx/Gfx.cpp +++ b/src/Components/Gfx/Gfx.cpp @@ -7,23 +7,33 @@ Gfx::Gfx(Pinetime::Drivers::St7789 &lcd) : lcd{lcd} { } void Gfx::Init() { - lcd.Init(); + } void Gfx::ClearScreen() { SetBackgroundColor(0x0000); + + state.remainingIterations = 240 + 1; + state.currentIteration = 0; + state.busy = true; + state.action = Action::FillRectangle; + lcd.BeginDrawBuffer(0, 0, width, height); - for(int i = 0; i < height; i++) { - lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); - } - lcd.EndDrawBuffer(); + lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); + while(state.busy) {} // TODO wait on an event/queue/... instead of polling } -void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint16_t color) { +void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t color) { SetBackgroundColor(color); - lcd.BeginDrawBuffer(0, 0, width, height); - lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2, 240); - lcd.EndDrawBuffer(); + + state.remainingIterations = 240 + 1; + state.currentIteration = 0; + state.busy = true; + state.action = Action::FillRectangle; + + lcd.BeginDrawBuffer(x, y, w, h); + lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); + while(state.busy) {} // TODO wait on an event/queue/... instead of polling } void Gfx::DrawString(uint8_t x, uint8_t y, uint16_t color, const char *text, const FONT_INFO *p_font, bool wrap) { @@ -64,31 +74,37 @@ void Gfx::DrawString(uint8_t x, uint8_t y, uint16_t color, const char *text, con void Gfx::DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint16_t color) { uint8_t char_idx = c - font->startChar; uint16_t bytes_in_line = CEIL_DIV(font->charInfo[char_idx].widthBits, 8); + uint16_t bg = 0x0000; if (c == ' ') { *x += font->height / 2; return; } - // TODO For now, LCD and SPI driver start a new transfer (cs pin + set address windows + write byte) FOR EACH PIXEL! - // This could be improved by setting CS pin, DC pin and address window ONLY ONCE for the whole character - - lcd.BeginDrawBuffer(*x, y, bytes_in_line*8, font->height); - uint16_t bg = 0x0000; - for (uint16_t i = 0; i < font->height; i++) { - for (uint16_t j = 0; j < bytes_in_line; j++) { - for (uint8_t k = 0; k < 8; k++) { - if ((1 << (7 - k)) & font->data[font->charInfo[char_idx].offset + i * bytes_in_line + j]) { - buffer[(j*8)+k] = color; - } - else { - buffer[(j*8)+k] = bg; - } + // Build first line + for (uint16_t j = 0; j < bytes_in_line; j++) { + for (uint8_t k = 0; k < 8; k++) { + if ((1 << (7 - k)) & font->data[font->charInfo[char_idx].offset + j]) { + buffer[(j*8)+k] = color; + } + else { + buffer[(j*8)+k] = bg; } } - lcd.NextDrawBuffer(reinterpret_cast(&buffer), bytes_in_line*8*2); } - lcd.EndDrawBuffer(); + + state.remainingIterations = font->height + 0; + state.currentIteration = 0; + state.busy = true; + state.action = Action::DrawChar; + state.font = const_cast(font); + state.character = c; + state.color = color; + + lcd.BeginDrawBuffer(*x, y, bytes_in_line*8, font->height); + lcd.NextDrawBuffer(reinterpret_cast(&buffer), bytes_in_line*8*2); + while(state.busy) {} // TODO wait on an event/queue/... instead of polling + *x += font->charInfo[char_idx].widthBits + font->spacePixels; } @@ -110,4 +126,40 @@ void Gfx::SetBackgroundColor(uint16_t color) { } } +bool Gfx::GetNextBuffer(uint8_t **data, size_t &size) { + if(!state.busy) return false; + state.remainingIterations--; + if (state.remainingIterations == 0) { + state.busy = false; + return false; + } + + if(state.action == Action::FillRectangle) { + *data = reinterpret_cast(buffer); + size = width * 2; + } else if(state.action == Action::DrawChar) { + uint16_t bg = 0x0000; + uint8_t char_idx = state.character - state.font->startChar; + uint16_t bytes_in_line = CEIL_DIV(state.font->charInfo[char_idx].widthBits, 8); + + for (uint16_t j = 0; j < bytes_in_line; j++) { + for (uint8_t k = 0; k < 8; k++) { + if ((1 << (7 - k)) & state.font->data[state.font->charInfo[char_idx].offset + ((state.currentIteration+1) * bytes_in_line) + j]) { + buffer[(j*8)+k] = state.color; + } + else { + buffer[(j*8)+k] = bg; + } + } + } + + *data = reinterpret_cast(buffer); + size = bytes_in_line*8*2; + } + + state.currentIteration++; + + return true; +} + diff --git a/src/Components/Gfx/Gfx.h b/src/Components/Gfx/Gfx.h index d872870..81c5f38 100644 --- a/src/Components/Gfx/Gfx.h +++ b/src/Components/Gfx/Gfx.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include namespace Pinetime { @@ -8,7 +9,7 @@ namespace Pinetime { class St7789; } namespace Components { - class Gfx { + class Gfx : public Pinetime::Drivers::BufferProvider { public: explicit Gfx(Drivers::St7789& lcd); void Init(); @@ -19,11 +20,26 @@ namespace Pinetime { void Sleep(); void Wakeup(); + bool GetNextBuffer(uint8_t **buffer, size_t &size) override; private: static constexpr uint8_t width = 240; static constexpr uint8_t height = 240; + enum class Action { None, FillRectangle, DrawChar}; + struct State { + State() : busy{false}, action{Action::None}, remainingIterations{0}, currentIteration{0} {} + volatile bool busy; + volatile Action action; + volatile uint16_t remainingIterations; + volatile uint16_t currentIteration; + volatile FONT_INFO *font; + volatile uint16_t color; + volatile uint8_t character; + }; + + volatile State state; + uint16_t buffer[width]; // 1 line buffer Drivers::St7789& lcd; diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index c1561cc..8795416 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -14,25 +14,20 @@ using namespace Pinetime::Applications; -DisplayApp::DisplayApp(Controllers::Battery &batteryController, +DisplayApp::DisplayApp(Pinetime::Drivers::St7789& lcd, + Pinetime::Components::Gfx& gfx, + Pinetime::Drivers::Cst816S& touchPanel, + Controllers::Battery &batteryController, Controllers::Ble &bleController, Controllers::DateTime &dateTimeController) : - spi{Drivers::SpiMaster::SpiModule::SPI0, { - Drivers::SpiMaster::BitOrder::Msb_Lsb, - Drivers::SpiMaster::Modes::Mode3, - Drivers::SpiMaster::Frequencies::Freq8Mhz, - pinSpiSck, - pinSpiMosi, - pinSpiMiso, - pinSpiCsn - }}, - lcd{new Drivers::St7789(spi, pinLcdDataCommand)}, - gfx{new Components::Gfx(*lcd.get()) }, + lcd{lcd}, + gfx{gfx}, + touchPanel{touchPanel}, batteryController{batteryController}, bleController{bleController}, dateTimeController{dateTimeController}, - clockScreen{*(gfx.get())}, - messageScreen{*(gfx.get())} { + clockScreen{gfx}, + messageScreen{gfx} { msgQueue = xQueueCreate(queueSize, itemSize); currentScreen = &clockScreen; } @@ -59,22 +54,19 @@ void DisplayApp::InitHw() { nrf_gpio_pin_clear(pinLcdBacklight2); nrf_gpio_pin_clear(pinLcdBacklight3); - spi.Init(); - gfx->Init(); currentScreen->Refresh(true); - touchPanel.Init(); } uint32_t acc = 0; uint32_t count = 0; bool toggle = true; void DisplayApp::Refresh() { - +#if 0 uint32_t before = nrf_rtc_counter_get(portNRF_RTC_REG); if(toggle) { - gfx->FillRectangle(0,0,240,240,0x0000); + gfx.FillRectangle(0,0,240,240,0x0000); } else { - gfx->FillRectangle(0,0,240,240,0xffff); + gfx.FillRectangle(0,0,240,240,0xffff); } uint32_t after = nrf_rtc_counter_get(portNRF_RTC_REG); @@ -85,8 +77,9 @@ void DisplayApp::Refresh() { } count++; toggle = !toggle; +#endif -#if 0 +#if 1 TickType_t queueTimeout; switch (state) { case States::Idle: @@ -108,16 +101,16 @@ void DisplayApp::Refresh() { nrf_gpio_pin_set(pinLcdBacklight2); vTaskDelay(100); nrf_gpio_pin_set(pinLcdBacklight1); - lcd->DisplayOff(); - lcd->Sleep(); + lcd.DisplayOff(); + lcd.Sleep(); touchPanel.Sleep(); state = States::Idle; break; case Messages::GoToRunning: - lcd->Wakeup(); + lcd.Wakeup(); touchPanel.Wakeup(); - lcd->DisplayOn(); + lcd.DisplayOn(); nrf_gpio_pin_clear(pinLcdBacklight3); nrf_gpio_pin_clear(pinLcdBacklight2); nrf_gpio_pin_clear(pinLcdBacklight1); @@ -179,7 +172,7 @@ void DisplayApp::OnTouchEvent() { auto info = touchPanel.GetTouchInfo(); if(info.isTouch) { - gfx->FillRectangle(info.x-10, info.y-10, 20,20, pointColor); + gfx.FillRectangle(info.x-10, info.y-10, 20,20, pointColor); pointColor+=10; } } diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h index eabfe09..0426542 100644 --- a/src/DisplayApp/DisplayApp.h +++ b/src/DisplayApp/DisplayApp.h @@ -23,7 +23,10 @@ namespace Pinetime { public: enum class States {Idle, Running}; enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent} ; - DisplayApp(Controllers::Battery &batteryController, + DisplayApp(Pinetime::Drivers::St7789& lcd, + Pinetime::Components::Gfx& gfx, + Pinetime::Drivers::Cst816S&, + Controllers::Battery &batteryController, Controllers::Ble &bleController, Controllers::DateTime& dateTimeController); void Start(); @@ -33,9 +36,8 @@ namespace Pinetime { TaskHandle_t taskHandle; static void Process(void* instance); void InitHw(); - Pinetime::Drivers::SpiMaster spi; - std::unique_ptr lcd; - std::unique_ptr gfx; + Pinetime::Drivers::St7789& lcd; + Pinetime::Components::Gfx& gfx; const FONT_INFO largeFont {lCD_70ptFontInfo.height, lCD_70ptFontInfo.startChar, lCD_70ptFontInfo.endChar, lCD_70ptFontInfo.spacePixels, lCD_70ptFontInfo.charInfo, lCD_70ptFontInfo.data}; const FONT_INFO smallFont {lCD_14ptFontInfo.height, lCD_14ptFontInfo.startChar, lCD_14ptFontInfo.endChar, lCD_14ptFontInfo.spacePixels, lCD_14ptFontInfo.charInfo, lCD_14ptFontInfo.data}; void Refresh(); @@ -52,18 +54,13 @@ namespace Pinetime { Pinetime::Controllers::Ble &bleController; Pinetime::Controllers::DateTime& dateTimeController; - Pinetime::Drivers::Cst816S touchPanel; + Pinetime::Drivers::Cst816S& touchPanel; void OnTouchEvent(); Screens::Clock clockScreen; Screens::Screen* currentScreen = nullptr; Screens::Message messageScreen; bool screenState = false; - static constexpr uint8_t pinSpiSck = 2; - static constexpr uint8_t pinSpiMosi = 3; - static constexpr uint8_t pinSpiMiso = 4; - static constexpr uint8_t pinSpiCsn = 25; - static constexpr uint8_t pinLcdDataCommand = 18; static constexpr uint8_t pinLcdBacklight1 = 14; static constexpr uint8_t pinLcdBacklight2 = 22; static constexpr uint8_t pinLcdBacklight3 = 23; diff --git a/src/drivers/BufferProvider.h b/src/drivers/BufferProvider.h new file mode 100644 index 0000000..50fa253 --- /dev/null +++ b/src/drivers/BufferProvider.h @@ -0,0 +1,11 @@ +#pragma once +#include + +namespace Pinetime { + namespace Drivers { + class BufferProvider { + public: + virtual bool GetNextBuffer(uint8_t** buffer, size_t& size) = 0; + }; + } +} \ No newline at end of file diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 7c6186a..84243a9 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -4,10 +4,9 @@ #include using namespace Pinetime::Drivers; -SpiMaster* spiInstance; SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters ¶ms) : spi{spi}, params{params} { - spiInstance = this; + } bool SpiMaster::Init() { @@ -84,12 +83,33 @@ void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_ NRF_PPI->CHENSET = 1U << ppi_channel; } -void SpiMaster::irqStarted() { - if(busy) { - auto s = currentBufferSize; - if(s > 0) { - auto currentSize = std::min((size_t)255, s); +void SpiMaster::OnEndEvent(BufferProvider& provider) { + if(!busy) return; + + auto s = currentBufferSize; + if(s > 0) { + auto currentSize = std::min((size_t) 255, s); + + NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; + NRF_SPIM0->TXD.MAXCNT = currentSize; + NRF_SPIM0->TXD.LIST = 0; + currentBufferAddr += currentSize; + currentBufferSize -= currentSize; + + NRF_SPIM0->RXD.PTR = (uint32_t) 0; + NRF_SPIM0->RXD.MAXCNT = 0; + NRF_SPIM0->RXD.LIST = 0; + + NRF_SPIM0->TASKS_START = 1; + } else { + uint8_t* buffer = nullptr; + size_t size = 0; + if(provider.GetNextBuffer(&buffer, size)) { + currentBufferAddr = (uint32_t) buffer; + currentBufferSize = size; + auto s = currentBufferSize; + auto currentSize = std::min((size_t)255, s); NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; NRF_SPIM0->TXD.MAXCNT = currentSize; NRF_SPIM0->TXD.LIST = 0; @@ -101,44 +121,19 @@ void SpiMaster::irqStarted() { NRF_SPIM0->RXD.MAXCNT = 0; NRF_SPIM0->RXD.LIST = 0; - if(repeat == 0) - NRF_SPIM0->SHORTS = 0; - - return; - }else { - if(repeat > 0) { - repeat = repeat -1; - - currentBufferAddr = bufferAddr; - currentBufferSize = bufferSize; - s = currentBufferSize; - auto currentSize = std::min((size_t)255, s); - NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; - NRF_SPIM0->TXD.MAXCNT = currentSize; - NRF_SPIM0->TXD.LIST = 0; - - currentBufferAddr += currentSize; - currentBufferSize -= currentSize; - - NRF_SPIM0->RXD.PTR = (uint32_t) 0; - NRF_SPIM0->RXD.MAXCNT = 0; - NRF_SPIM0->RXD.LIST = 0; - } - } - } -} - -void SpiMaster::irqEnd() { - if(busy) { - if(repeat == 0 && currentBufferSize == 0) { - nrf_gpio_pin_set(pinCsn); + NRF_SPIM0->TASKS_START = 1; + } else { busy = false; + nrf_gpio_pin_set(pinCsn); } } } +void SpiMaster::OnStartedEvent(BufferProvider& provider) { + if(!busy) return; +} -bool SpiMaster::Write(const uint8_t *data, size_t size, size_t r) { +bool SpiMaster::Write(const uint8_t *data, size_t size) { if(data == nullptr) return false; while(busy) { @@ -162,16 +157,12 @@ bool SpiMaster::Write(const uint8_t *data, size_t size, size_t r) { nrf_gpio_pin_clear(pinCsn); - currentBufferAddr = bufferAddr = (uint32_t)data; - currentBufferSize = bufferSize = size; - repeat = r; + currentBufferAddr = (uint32_t)data; + currentBufferSize = size; busy = true; - if(repeat > 0) - NRF_SPIM0->SHORTS = (1<<17); - - auto currentSize = std::min((size_t)255, bufferSize); - NRF_SPIM0->TXD.PTR = bufferAddr; + auto currentSize = std::min((size_t)255, (size_t)currentBufferSize); + NRF_SPIM0->TXD.PTR = currentBufferAddr; NRF_SPIM0->TXD.MAXCNT = currentSize; NRF_SPIM0->TXD.LIST = 0; @@ -187,21 +178,11 @@ bool SpiMaster::Write(const uint8_t *data, size_t size, size_t r) { if(size == 1) { while (NRF_SPIM0->EVENTS_END == 0); busy = false; - nrf_gpio_pin_set(pinCsn); } - return true; } -bool SpiMaster::GetStatusEnd() { - return (bool)*(volatile uint32_t *)((uint8_t *)spiBaseAddress + (uint32_t)NRF_SPIM_EVENT_END); -} - -bool SpiMaster::GetStatusStarted() { - return (bool)*(volatile uint32_t *)((uint8_t *)spiBaseAddress + (uint32_t)NRF_SPIM_EVENT_STARTED); -} - void SpiMaster::Sleep() { while(NRF_SPIM0->ENABLE != 0) { NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); @@ -216,8 +197,4 @@ void SpiMaster::Wakeup() { Init(); } -void SpiMaster::Wait() { - while(busy) { - asm("nop"); - } -} + diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index ee03186..7dac747 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -3,6 +3,8 @@ #include #include #include + +#include "BufferProvider.h" namespace Pinetime { namespace Drivers { class SpiMaster { @@ -23,20 +25,17 @@ namespace Pinetime { SpiMaster(const SpiModule spi, const Parameters& params); bool Init(); - bool Write(const uint8_t* data, size_t size, size_t r = 0); - void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); - void Wait(); + bool Write(const uint8_t* data, size_t size); + + void OnStartedEvent(BufferProvider& provider); + void OnEndEvent(BufferProvider& provider); void Sleep(); void Wakeup(); - bool GetStatusEnd(); - bool GetStatusStarted(); - - void irqEnd(); - void irqStarted(); - private: + void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); + NRF_SPIM_Type * spiBaseAddress; uint8_t pinCsn; @@ -44,12 +43,8 @@ namespace Pinetime { SpiMaster::Parameters params; volatile bool busy = false; - - uint32_t bufferAddr = 0; volatile uint32_t currentBufferAddr = 0; - size_t bufferSize = 0; volatile size_t currentBufferSize = 0; - volatile uint32_t repeat = 0; }; } } diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index 6b66313..39595dc 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -37,8 +37,8 @@ void St7789::WriteData(uint8_t data) { } -void St7789::WriteSpi(const uint8_t* data, size_t size, size_t repeat) { - spi.Write(data, size, repeat); +void St7789::WriteSpi(const uint8_t* data, size_t size) { + spi.Write(data, size); } void St7789::SoftwareReset() { @@ -142,12 +142,8 @@ void St7789::BeginDrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t he nrf_gpio_pin_set(pinDataCommand); } -void St7789::EndDrawBuffer() { - spi.Wait(); -} - -void St7789::NextDrawBuffer(const uint8_t *data, size_t size, size_t repeat) { - WriteSpi(data, size, repeat); +void St7789::NextDrawBuffer(const uint8_t *data, size_t size) { + WriteSpi(data, size); } void St7789::HardwareReset() { @@ -178,5 +174,3 @@ void St7789::Wakeup() { NormalModeOn(); DisplayOn(); } - - diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index eef051b..9ecf9f2 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -12,16 +12,13 @@ namespace Pinetime { void DrawPixel(uint16_t x, uint16_t y, uint32_t color); void BeginDrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height); - void NextDrawBuffer(const uint8_t* data, size_t size, size_t repeat = 0); - void EndDrawBuffer(); + void NextDrawBuffer(const uint8_t* data, size_t size); void DisplayOn(); void DisplayOff(); void Sleep(); void Wakeup(); - - private: SpiMaster& spi; uint8_t pinDataCommand; @@ -35,12 +32,9 @@ namespace Pinetime { void DisplayInversionOn(); void NormalModeOn(); void WriteToRam(); - - void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); - void WriteCommand(uint8_t cmd); - void WriteSpi(const uint8_t* data, size_t size, size_t repeat = 0); + void WriteSpi(const uint8_t* data, size_t size); enum class Commands : uint8_t { SoftwareReset = 0x01, @@ -62,7 +56,6 @@ namespace Pinetime { static constexpr uint16_t Width = 240; static constexpr uint16_t Height = 240; void RowAddressSet(); - }; } } diff --git a/src/main.cpp b/src/main.cpp index 284113c..13dddca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,10 @@ #include "BLE/BleManager.h" #include "Components/Battery/BatteryController.h" #include "Components/Ble/BleController.h" +#include "../drivers/Cst816s.h" +#include +#include +#include #if NRF_LOG_ENABLED #include "Logging/NrfLogger.h" @@ -24,6 +28,18 @@ Pinetime::Logging::NrfLogger logger; Pinetime::Logging::DummyLogger logger; #endif +std::unique_ptr spi; +std::unique_ptr lcd; +std::unique_ptr gfx; +std::unique_ptr touchPanel; + +static constexpr uint8_t pinSpiSck = 2; +static constexpr uint8_t pinSpiMosi = 3; +static constexpr uint8_t pinSpiMiso = 4; +static constexpr uint8_t pinSpiCsn = 25; +static constexpr uint8_t pinLcdDataCommand = 18; + + std::unique_ptr displayApp; TaskHandle_t systemThread; bool isSleeping = false; @@ -85,9 +101,29 @@ void SystemTask(void *) { APP_GPIOTE_INIT(2); bool erase_bonds=false; nrf_sdh_freertos_init(ble_manager_start_advertising, &erase_bonds); - displayApp->Start(); + spi.reset(new Pinetime::Drivers::SpiMaster {Pinetime::Drivers::SpiMaster::SpiModule::SPI0, { + Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb, + Pinetime::Drivers::SpiMaster::Modes::Mode3, + Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz, + pinSpiSck, + pinSpiMosi, + pinSpiMiso, + pinSpiCsn + }}); + + lcd.reset(new Pinetime::Drivers::St7789(*spi, pinLcdDataCommand)); + gfx.reset(new Pinetime::Components::Gfx(*lcd)); + touchPanel.reset(new Pinetime::Drivers::Cst816S()); + + spi->Init(); + lcd->Init(); + touchPanel->Init(); batteryController.Init(); + + displayApp.reset(new Pinetime::Applications::DisplayApp(*lcd, *gfx, *touchPanel, batteryController, bleController, dateTimeController)); + displayApp->Start(); + batteryController.Update(); displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateBatteryLevel); @@ -158,27 +194,22 @@ void OnNewTime(current_time_char_t* currentTime) { dayOfWeek, hour, minute, second, nrf_rtc_counter_get(portNRF_RTC_REG)); } -extern Pinetime::Drivers::SpiMaster* spiInstance; void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) { if(((NRF_SPIM0->INTENSET & (1<<6)) != 0) && NRF_SPIM0->EVENTS_END == 1) { NRF_SPIM0->EVENTS_END = 0; - spiInstance->irqEnd(); + spi->OnEndEvent(*gfx); } if(((NRF_SPIM0->INTENSET & (1<<19)) != 0) && NRF_SPIM0->EVENTS_STARTED == 1) { NRF_SPIM0->EVENTS_STARTED = 0; - spiInstance->irqStarted(); + spi->OnStartedEvent(*gfx); } - if(((NRF_SPIM0->INTENSET & (1<<1)) != 0) && NRF_SPIM0->EVENTS_STOPPED == 1) { NRF_SPIM0->EVENTS_STOPPED = 0; } - - return; } int main(void) { - displayApp.reset(new Pinetime::Applications::DisplayApp(batteryController, bleController, dateTimeController)); logger.Init(); nrf_drv_clock_init(); -- cgit v0.10.2 From 640e8cd1febc679b976fb26225aec8d462a4c241 Mon Sep 17 00:00:00 2001 From: JF Date: Sun, 26 Jan 2020 15:35:18 +0100 Subject: GFX : wait end of transfert using a task notification. Code cleaning in SpiMaster. diff --git a/src/Components/Gfx/Gfx.cpp b/src/Components/Gfx/Gfx.cpp index 2f64596..0dcb98a 100644 --- a/src/Components/Gfx/Gfx.cpp +++ b/src/Components/Gfx/Gfx.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include "Gfx.h" #include "../../drivers/St7789.h" using namespace Pinetime::Components; @@ -17,10 +19,12 @@ void Gfx::ClearScreen() { state.currentIteration = 0; state.busy = true; state.action = Action::FillRectangle; + state.taskToNotify = xTaskGetCurrentTaskHandle(); lcd.BeginDrawBuffer(0, 0, width, height); lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); - while(state.busy) {} // TODO wait on an event/queue/... instead of polling + WaitTransfertFinished(); + } void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t color) { @@ -30,10 +34,13 @@ void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t col state.currentIteration = 0; state.busy = true; state.action = Action::FillRectangle; + state.color = color; + state.taskToNotify = xTaskGetCurrentTaskHandle(); lcd.BeginDrawBuffer(x, y, w, h); lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); - while(state.busy) {} // TODO wait on an event/queue/... instead of polling + + WaitTransfertFinished(); } void Gfx::DrawString(uint8_t x, uint8_t y, uint16_t color, const char *text, const FONT_INFO *p_font, bool wrap) { @@ -100,10 +107,11 @@ void Gfx::DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint state.font = const_cast(font); state.character = c; state.color = color; + state.taskToNotify = xTaskGetCurrentTaskHandle(); lcd.BeginDrawBuffer(*x, y, bytes_in_line*8, font->height); lcd.NextDrawBuffer(reinterpret_cast(&buffer), bytes_in_line*8*2); - while(state.busy) {} // TODO wait on an event/queue/... instead of polling + WaitTransfertFinished(); *x += font->charInfo[char_idx].widthBits + font->spacePixels; } @@ -131,6 +139,7 @@ bool Gfx::GetNextBuffer(uint8_t **data, size_t &size) { state.remainingIterations--; if (state.remainingIterations == 0) { state.busy = false; + NotifyEndOfTransfert(state.taskToNotify); return false; } @@ -162,4 +171,16 @@ bool Gfx::GetNextBuffer(uint8_t **data, size_t &size) { return true; } +void Gfx::NotifyEndOfTransfert(TaskHandle_t task) { + if(task != nullptr) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(task, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } +} + +void Gfx::WaitTransfertFinished() const { + ulTaskNotifyTake(pdTRUE, 500); +} + diff --git a/src/Components/Gfx/Gfx.h b/src/Components/Gfx/Gfx.h index 81c5f38..f31b13c 100644 --- a/src/Components/Gfx/Gfx.h +++ b/src/Components/Gfx/Gfx.h @@ -2,6 +2,8 @@ #include #include #include +#include +#include namespace Pinetime { @@ -36,6 +38,7 @@ namespace Pinetime { volatile FONT_INFO *font; volatile uint16_t color; volatile uint8_t character; + volatile TaskHandle_t taskToNotify = nullptr; }; volatile State state; @@ -45,6 +48,8 @@ namespace Pinetime { void pixel_draw(uint8_t x, uint8_t y, uint16_t color); void SetBackgroundColor(uint16_t color); + void WaitTransfertFinished() const; + void NotifyEndOfTransfert(TaskHandle_t task); }; } } diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 84243a9..4a875b9 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -26,9 +26,9 @@ bool SpiMaster::Init() { } /* Configure pins, frequency and mode */ - NRF_SPIM0->PSELSCK = params.pinSCK; - NRF_SPIM0->PSELMOSI = params.pinMOSI; - NRF_SPIM0->PSELMISO = params.pinMISO; + spiBaseAddress->PSELSCK = params.pinSCK; + spiBaseAddress->PSELMOSI = params.pinMOSI; + spiBaseAddress->PSELMISO = params.pinMISO; nrf_gpio_pin_set(pinCsn); /* disable Set slave select (inactive high) */ uint32_t frequency; @@ -36,7 +36,7 @@ bool SpiMaster::Init() { case Frequencies::Freq8Mhz: frequency = 0x80000000; break; default: return false; } - NRF_SPIM0->FREQUENCY = frequency; + spiBaseAddress->FREQUENCY = frequency; uint32_t regConfig = 0; switch(params.bitOrder) { @@ -52,26 +52,24 @@ bool SpiMaster::Init() { default: return false; } - setup_workaround_for_ftpan_58(NRF_SPIM0, 0, 0); + spiBaseAddress->CONFIG = regConfig; + spiBaseAddress->EVENTS_ENDRX = 0; + spiBaseAddress->EVENTS_ENDTX = 0; + spiBaseAddress->EVENTS_END = 0; - NRF_SPIM0->CONFIG = regConfig; - NRF_SPIM0->EVENTS_ENDRX = 0; - NRF_SPIM0->EVENTS_ENDTX = 0; - NRF_SPIM0->EVENTS_END = 0; + spiBaseAddress->INTENSET = ((unsigned)1 << (unsigned)6); + spiBaseAddress->INTENSET = ((unsigned)1 << (unsigned)1); + spiBaseAddress->INTENSET = ((unsigned)1 << (unsigned)19); - NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)6); - NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)1); - NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)19); + spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); - NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); - - NRFX_IRQ_PRIORITY_SET(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn,6); + NRFX_IRQ_PRIORITY_SET(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn,2); NRFX_IRQ_ENABLE(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn); return true; } -void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel) { +void SpiMaster::SetupWorkaroundForFtpan58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel) { // Create an event when SCK toggles. NRF_GPIOTE->CONFIG[gpiote_channel] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | (spim->PSEL.SCK << GPIOTE_CONFIG_PSEL_Pos) | @@ -81,6 +79,21 @@ void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_ NRF_PPI->CH[ppi_channel].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[gpiote_channel]; NRF_PPI->CH[ppi_channel].TEP = (uint32_t) &spim->TASKS_STOP; NRF_PPI->CHENSET = 1U << ppi_channel; + + // Disable IRQ + spim->INTENCLR = (1<<6); + spim->INTENCLR = (1<<1); + spim->INTENCLR = (1<<19); +} + +void SpiMaster::DisableWorkaroundForFtpan58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel) { + NRF_GPIOTE->CONFIG[gpiote_channel] = 0; + NRF_PPI->CH[ppi_channel].EEP = 0; + NRF_PPI->CH[ppi_channel].TEP = 0; + NRF_PPI->CHENSET = ppi_channel; + spim->INTENSET = (1<<6); + spim->INTENSET = (1<<1); + spim->INTENSET = (1<<19); } void SpiMaster::OnEndEvent(BufferProvider& provider) { @@ -89,19 +102,11 @@ void SpiMaster::OnEndEvent(BufferProvider& provider) { auto s = currentBufferSize; if(s > 0) { auto currentSize = std::min((size_t) 255, s); - - NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; - NRF_SPIM0->TXD.MAXCNT = currentSize; - NRF_SPIM0->TXD.LIST = 0; - + PrepareTx(currentBufferAddr, currentSize); currentBufferAddr += currentSize; currentBufferSize -= currentSize; - NRF_SPIM0->RXD.PTR = (uint32_t) 0; - NRF_SPIM0->RXD.MAXCNT = 0; - NRF_SPIM0->RXD.LIST = 0; - - NRF_SPIM0->TASKS_START = 1; + spiBaseAddress->TASKS_START = 1; } else { uint8_t* buffer = nullptr; size_t size = 0; @@ -110,18 +115,11 @@ void SpiMaster::OnEndEvent(BufferProvider& provider) { currentBufferSize = size; auto s = currentBufferSize; auto currentSize = std::min((size_t)255, s); - NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; - NRF_SPIM0->TXD.MAXCNT = currentSize; - NRF_SPIM0->TXD.LIST = 0; - + PrepareTx(currentBufferAddr, currentSize); currentBufferAddr += currentSize; currentBufferSize -= currentSize; - NRF_SPIM0->RXD.PTR = (uint32_t) 0; - NRF_SPIM0->RXD.MAXCNT = 0; - NRF_SPIM0->RXD.LIST = 0; - - NRF_SPIM0->TASKS_START = 1; + spiBaseAddress->TASKS_START = 1; } else { busy = false; nrf_gpio_pin_set(pinCsn); @@ -133,6 +131,16 @@ void SpiMaster::OnStartedEvent(BufferProvider& provider) { if(!busy) return; } +void SpiMaster::PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size) { + spiBaseAddress->TXD.PTR = bufferAddress; + spiBaseAddress->TXD.MAXCNT = size; + spiBaseAddress->TXD.LIST = 0; + spiBaseAddress->RXD.PTR = 0; + spiBaseAddress->RXD.MAXCNT = 0; + spiBaseAddress->RXD.LIST = 0; + spiBaseAddress->EVENTS_END = 0; +} + bool SpiMaster::Write(const uint8_t *data, size_t size) { if(data == nullptr) return false; @@ -141,18 +149,9 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { } if(size == 1) { - setup_workaround_for_ftpan_58(NRF_SPIM0, 0,0); - NRF_SPIM0->INTENCLR = (1<<6); - NRF_SPIM0->INTENCLR = (1<<1); - NRF_SPIM0->INTENCLR = (1<<19); + SetupWorkaroundForFtpan58(spiBaseAddress, 0,0); } else { - NRF_GPIOTE->CONFIG[0] = 0; - NRF_PPI->CH[0].EEP = 0; - NRF_PPI->CH[0].TEP = 0; - NRF_PPI->CHENSET = 0; - NRF_SPIM0->INTENSET = (1<<6); - NRF_SPIM0->INTENSET = (1<<1); - NRF_SPIM0->INTENSET = (1<<19); + DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); } nrf_gpio_pin_clear(pinCsn); @@ -162,21 +161,13 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { busy = true; auto currentSize = std::min((size_t)255, (size_t)currentBufferSize); - NRF_SPIM0->TXD.PTR = currentBufferAddr; - NRF_SPIM0->TXD.MAXCNT = currentSize; - NRF_SPIM0->TXD.LIST = 0; - + PrepareTx(currentBufferAddr, currentSize); currentBufferSize -= currentSize; currentBufferAddr += currentSize; - - NRF_SPIM0->RXD.PTR = (uint32_t) 0; - NRF_SPIM0->RXD.MAXCNT = 0; - NRF_SPIM0->RXD.LIST = 0; - NRF_SPIM0->EVENTS_END = 0; - NRF_SPIM0->TASKS_START = 1; + spiBaseAddress->TASKS_START = 1; if(size == 1) { - while (NRF_SPIM0->EVENTS_END == 0); + while (spiBaseAddress->EVENTS_END == 0); busy = false; } @@ -184,8 +175,8 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { } void SpiMaster::Sleep() { - while(NRF_SPIM0->ENABLE != 0) { - NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); + while(spiBaseAddress->ENABLE != 0) { + spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); } nrf_gpio_cfg_default(params.pinSCK); nrf_gpio_cfg_default(params.pinMOSI); diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 7dac747..6001324 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -34,7 +34,9 @@ namespace Pinetime { void Wakeup(); private: - void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); + void SetupWorkaroundForFtpan58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); + void DisableWorkaroundForFtpan58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); + void PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size); NRF_SPIM_Type * spiBaseAddress; uint8_t pinCsn; -- cgit v0.10.2 From 6491a7c3a0738d6e6ef3bf57da460f61298d1cd9 Mon Sep 17 00:00:00 2001 From: JF Date: Sun, 26 Jan 2020 15:39:49 +0100 Subject: Remove test code diff --git a/CMakeLists.txt b/CMakeLists.txt index 21c6379..a8d8426 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(pinetime VERSION 0.2.99 LANGUAGES C CXX ASM) +project(pinetime VERSION 0.2.1 LANGUAGES C CXX ASM) set(NRF_TARGET "nrf52") diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index 8795416..ca13942 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -26,8 +26,7 @@ DisplayApp::DisplayApp(Pinetime::Drivers::St7789& lcd, batteryController{batteryController}, bleController{bleController}, dateTimeController{dateTimeController}, - clockScreen{gfx}, - messageScreen{gfx} { + clockScreen{gfx} { msgQueue = xQueueCreate(queueSize, itemSize); currentScreen = &clockScreen; } @@ -61,25 +60,6 @@ uint32_t acc = 0; uint32_t count = 0; bool toggle = true; void DisplayApp::Refresh() { -#if 0 - uint32_t before = nrf_rtc_counter_get(portNRF_RTC_REG); - if(toggle) { - gfx.FillRectangle(0,0,240,240,0x0000); - } else { - gfx.FillRectangle(0,0,240,240,0xffff); - } - uint32_t after = nrf_rtc_counter_get(portNRF_RTC_REG); - - acc += (after - before); - if((count % 10) == 0) { - NRF_LOG_INFO("DRAW : %d ms", (uint32_t)(acc/10)); - acc = 0; - } - count++; - toggle = !toggle; -#endif - -#if 1 TickType_t queueTimeout; switch (state) { case States::Idle: @@ -130,29 +110,16 @@ void DisplayApp::Refresh() { break; } } -#endif } void DisplayApp::RunningState() { clockScreen.SetCurrentDateTime(dateTimeController.CurrentDateTime()); -// if(currentScreen != nullptr) { -// currentScreen->Refresh(false); -// } - if(currentScreen != nullptr) { - currentScreen->Refresh(true); - } - - if(screenState) { - currentScreen = &clockScreen; - } else { - currentScreen = &messageScreen; + currentScreen->Refresh(false); } - screenState = !screenState; } - void DisplayApp::IdleState() { } diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h index 0426542..5a5d3ee 100644 --- a/src/DisplayApp/DisplayApp.h +++ b/src/DisplayApp/DisplayApp.h @@ -59,8 +59,6 @@ namespace Pinetime { Screens::Clock clockScreen; Screens::Screen* currentScreen = nullptr; - Screens::Message messageScreen; - bool screenState = false; static constexpr uint8_t pinLcdBacklight1 = 14; static constexpr uint8_t pinLcdBacklight2 = 22; static constexpr uint8_t pinLcdBacklight3 = 23; diff --git a/src/sdk_config.h b/src/sdk_config.h index e74751e..2136320 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -8452,15 +8452,15 @@ // NRF_LOG_ENABLED - nrf_log - Logger //========================================================== #ifndef NRF_LOG_ENABLED -#define NRF_LOG_ENABLED 1 +#define NRF_LOG_ENABLED 0 #endif #ifndef NRF_LOG_BACKEND_RTT_ENABLED -#define NRF_LOG_BACKEND_RTT_ENABLED 1 +#define NRF_LOG_BACKEND_RTT_ENABLED 0 #endif #ifndef NRF_LOG_BACKEND_SERIAL_USES_RTT -#define NRF_LOG_BACKEND_SERIAL_USES_RTT 1 +#define NRF_LOG_BACKEND_SERIAL_USES_RTT 0 #endif // Log message pool - Configuration of log message pool -- cgit v0.10.2