diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/Cst816s.cpp | 24 | ||||
| -rw-r--r-- | src/drivers/Cst816s.h | 14 | ||||
| -rw-r--r-- | src/drivers/Spi.cpp | 13 | ||||
| -rw-r--r-- | src/drivers/SpiMaster.cpp | 6 | ||||
| -rw-r--r-- | src/drivers/SpiNorFlash.cpp | 22 | ||||
| -rw-r--r-- | src/drivers/SpiNorFlash.h | 4 | ||||
| -rw-r--r-- | src/drivers/St7789.cpp | 6 | ||||
| -rw-r--r-- | src/drivers/TwiMaster.cpp | 111 | ||||
| -rw-r--r-- | src/drivers/TwiMaster.h | 19 |
9 files changed, 173 insertions, 46 deletions
diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index 60cd402c..94db3b34 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -2,7 +2,6 @@ #include <task.h> #include <nrfx_log.h> #include <legacy/nrf_drv_gpiote.h> - #include "Cst816s.h" using namespace Pinetime::Drivers; @@ -38,7 +37,9 @@ void Cst816S::Init() { Cst816S::TouchInfos Cst816S::GetTouchInfo() { Cst816S::TouchInfos info; - twiMaster.Read(twiAddress, 0, touchData, 63); + auto ret = twiMaster.Read(twiAddress, 0, touchData, 63); + if(ret != TwiMaster::ErrorCodes::NoError) return {}; + auto nbTouchPoints = touchData[2] & 0x0f; // uint8_t i = 0; @@ -60,9 +61,9 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { uint16_t y = (yHigh << 8) | yLow; auto action = touchData[touchEventIndex + (touchStep * i)] >> 6; /* 0 = Down, 1 = Up, 2 = contact*/ - auto finger = touchData[touchIdIndex + (touchStep * i)] >> 4; - auto pressure = touchData[touchXYIndex + (touchStep * i)]; - auto area = touchData[touchMiscIndex + (touchStep * i)] >> 4; + //auto finger = touchData[touchIdIndex + (touchStep * i)] >> 4; + //auto pressure = touchData[touchXYIndex + (touchStep * i)]; + //auto area = touchData[touchMiscIndex + (touchStep * i)] >> 4; info.x = x; info.y = y; @@ -89,7 +90,6 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { // case Gestures::LongPress: NRF_LOG_INFO("Gesture : Long press"); break; // default : NRF_LOG_INFO("Unknown"); break; // } - } @@ -97,12 +97,16 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { } void Cst816S::Sleep() { - // TODO re enable sleep mode - //twiMaster.Sleep(); - nrf_gpio_cfg_default(6); - nrf_gpio_cfg_default(7); + nrf_gpio_pin_clear(pinReset); + vTaskDelay(5); + nrf_gpio_pin_set(pinReset); + vTaskDelay(50); + static constexpr uint8_t sleepValue = 0x03; + twiMaster.Write(twiAddress, 0xA5, &sleepValue, 1); + NRF_LOG_INFO("[TOUCHPANEL] Sleep"); } void Cst816S::Wakeup() { Init(); + NRF_LOG_INFO("[TOUCHPANEL] Wakeup"); }
\ No newline at end of file diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h index b115a688..4569e82f 100644 --- a/src/drivers/Cst816s.h +++ b/src/drivers/Cst816s.h @@ -18,13 +18,13 @@ namespace Pinetime { LongPress = 0x0C }; struct TouchInfos { - uint16_t x; - uint16_t y; - uint8_t action; - uint8_t finger; - uint8_t pressure; - uint8_t area; - Gestures gesture; + uint16_t x = 0; + uint16_t y = 0; + uint8_t action = 0; + uint8_t finger = 0; + uint8_t pressure = 0; + uint8_t area = 0; + Gestures gesture = Gestures::None; bool isTouch = false; }; diff --git a/src/drivers/Spi.cpp b/src/drivers/Spi.cpp index bf08178d..2d8aa3b8 100644 --- a/src/drivers/Spi.cpp +++ b/src/drivers/Spi.cpp @@ -1,4 +1,5 @@ #include <hal/nrf_gpio.h> +#include <nrfx_log.h> #include "Spi.h" using namespace Pinetime::Drivers; @@ -18,8 +19,12 @@ bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize) { } void Spi::Sleep() { - // TODO sleep spi nrf_gpio_cfg_default(pinCsn); + NRF_LOG_INFO("[SPI] Sleep") +} + +bool Spi::WriteCmdAndBuffer(const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) { + return spiMaster.WriteCmdAndBuffer(pinCsn, cmd, cmdSize, data, dataSize); } bool Spi::Init() { @@ -27,8 +32,10 @@ bool Spi::Init() { return true; } -bool Spi::WriteCmdAndBuffer(const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) { - return spiMaster.WriteCmdAndBuffer(pinCsn, cmd, cmdSize, data, dataSize); +void Spi::Wakeup() { + nrf_gpio_cfg_output(pinCsn); + nrf_gpio_pin_set(pinCsn); + NRF_LOG_INFO("[SPI] Wakeup") } diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 8087d386..2e5852a5 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -4,6 +4,7 @@ #include "SpiMaster.h" #include <algorithm> #include <task.h> +#include <nrfx_log.h> using namespace Pinetime::Drivers; @@ -117,8 +118,6 @@ void SpiMaster::OnEndEvent() { spiBaseAddress->TASKS_START = 1; } else { - uint8_t* buffer = nullptr; - size_t size = 0; if(taskToNotify != nullptr) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken); @@ -233,10 +232,13 @@ void SpiMaster::Sleep() { nrf_gpio_cfg_default(params.pinSCK); nrf_gpio_cfg_default(params.pinMOSI); nrf_gpio_cfg_default(params.pinMISO); + + NRF_LOG_INFO("[SPIMASTER] sleep") } void SpiMaster::Wakeup() { Init(); + NRF_LOG_INFO("[SPIMASTER] Wakeup"); } bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) { diff --git a/src/drivers/SpiNorFlash.cpp b/src/drivers/SpiNorFlash.cpp index 7e4da1ca..bd24834e 100644 --- a/src/drivers/SpiNorFlash.cpp +++ b/src/drivers/SpiNorFlash.cpp @@ -11,8 +11,8 @@ SpiNorFlash::SpiNorFlash(Spi& spi) : spi{spi} { } void SpiNorFlash::Init() { - auto id = ReadIdentificaion(); - NRF_LOG_INFO("[SPI FLASH] Manufacturer : %d, Memory type : %d, memory density : %d", id.manufacturer, id.type, id.density); + device_id = ReadIdentificaion(); + NRF_LOG_INFO("[SpiNorFlash] Manufacturer : %d, Memory type : %d, memory density : %d", device_id.manufacturer, device_id.type, device_id.density); } void SpiNorFlash::Uninit() { @@ -20,11 +20,25 @@ void SpiNorFlash::Uninit() { } void SpiNorFlash::Sleep() { - + auto cmd = static_cast<uint8_t>(Commands::DeepPowerDown); + spi.Write(&cmd, sizeof(uint8_t)); + NRF_LOG_INFO("[SpiNorFlash] Sleep") } void SpiNorFlash::Wakeup() { - + // send Commands::ReleaseFromDeepPowerDown then 3 dummy bytes before reading Device ID + static constexpr uint8_t cmdSize = 4; + uint8_t cmd[cmdSize] = {static_cast<uint8_t>(Commands::ReleaseFromDeepPowerDown), 0x01, 0x02, 0x03}; + uint8_t id = 0; + spi.Read(reinterpret_cast<uint8_t *>(&cmd), cmdSize, &id, 1); + auto devId = device_id = ReadIdentificaion(); + if(devId.type != device_id.type) { + NRF_LOG_INFO("[SpiNorFlash] ID on Wakeup: Failed"); + } + else { + NRF_LOG_INFO("[SpiNorFlash] ID on Wakeup: %d", id); + } + NRF_LOG_INFO("[SpiNorFlash] Wakeup") } SpiNorFlash::Identification SpiNorFlash::ReadIdentificaion() { diff --git a/src/drivers/SpiNorFlash.h b/src/drivers/SpiNorFlash.h index 98267c09..10c25a01 100644 --- a/src/drivers/SpiNorFlash.h +++ b/src/drivers/SpiNorFlash.h @@ -48,11 +48,13 @@ namespace Pinetime { SectorErase = 0x20, ReadSecurityRegister = 0x2B, ReadIdentification = 0x9F, + ReleaseFromDeepPowerDown = 0xAB, + DeepPowerDown = 0xB9 }; static constexpr uint16_t pageSize = 256; Spi& spi; - + Identification device_id; }; } } diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index 09269afd..ed28c82c 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -1,5 +1,6 @@ #include <hal/nrf_gpio.h> #include <libraries/delay/nrf_delay.h> +#include <nrfx_log.h> #include "St7789.h" #include "Spi.h" @@ -174,12 +175,10 @@ void St7789::HardwareReset() { void St7789::Sleep() { SleepIn(); nrf_gpio_cfg_default(pinDataCommand); -// spi.Sleep(); // TODO sleep SPI + NRF_LOG_INFO("[LCD] Sleep"); } void St7789::Wakeup() { -// spi.Wakeup(); // TODO wake up SPI - nrf_gpio_cfg_output(pinDataCommand); // TODO why do we need to reset the controller? HardwareReset(); @@ -193,4 +192,5 @@ void St7789::Wakeup() { NormalModeOn(); VerticalScrollStartAddress(verticalScrollingStartAddress); DisplayOn(); + NRF_LOG_INFO("[LCD] Wakeup") } diff --git a/src/drivers/TwiMaster.cpp b/src/drivers/TwiMaster.cpp index 4a0c536d..3ff8a952 100644 --- a/src/drivers/TwiMaster.cpp +++ b/src/drivers/TwiMaster.cpp @@ -60,24 +60,53 @@ void TwiMaster::Init() { } -void TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, size_t size) { +TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, size_t size) { xSemaphoreTake(mutex, portMAX_DELAY); - Write(deviceAddress, ®isterAddress, 1, false); - Read(deviceAddress, data, size, true); + auto ret = ReadWithRetry(deviceAddress, registerAddress, data, size); xSemaphoreGive(mutex); + + return ret; } -void TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t *data, size_t size) { +TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t *data, size_t size) { ASSERT(size <= maxDataSize); xSemaphoreTake(mutex, portMAX_DELAY); + + auto ret = WriteWithRetry(deviceAddress, registerAddress, data, size); + xSemaphoreGive(mutex); + return ret; +} + +/* Execute a read transaction (composed of a write and a read operation). If one of these opeartion fails, + * it's retried once. If it fails again, an error is returned */ +TwiMaster::ErrorCodes TwiMaster::ReadWithRetry(uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, size_t size) { + TwiMaster::ErrorCodes ret; + ret = Write(deviceAddress, ®isterAddress, 1, false); + if(ret != ErrorCodes::NoError) + ret = Write(deviceAddress, ®isterAddress, 1, false); + + if(ret != ErrorCodes::NoError) return ret; + + ret = Read(deviceAddress, data, size, true); + if(ret != ErrorCodes::NoError) + ret = Read(deviceAddress, data, size, true); + + return ret; +} + +/* Execute a write transaction. If it fails, it is retried once. If it fails again, an error is returned. */ +TwiMaster::ErrorCodes TwiMaster::WriteWithRetry(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t *data, size_t size) { internalBuffer[0] = registerAddress; std::memcpy(internalBuffer+1, data, size); - Write(deviceAddress, internalBuffer, size+1, true); - xSemaphoreGive(mutex); + auto ret = Write(deviceAddress, internalBuffer, size+1, true); + if(ret != ErrorCodes::NoError) + ret = Write(deviceAddress, internalBuffer, size+1, true); + + return ret; } -void TwiMaster::Read(uint8_t deviceAddress, uint8_t *buffer, size_t size, bool stop) { +TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t *buffer, size_t size, bool stop) { twiBaseAddress->ADDRESS = deviceAddress; twiBaseAddress->TASKS_RESUME = 0x1UL; twiBaseAddress->RXD.PTR = (uint32_t)buffer; @@ -88,7 +117,15 @@ void TwiMaster::Read(uint8_t deviceAddress, uint8_t *buffer, size_t size, bool s while(!twiBaseAddress->EVENTS_RXSTARTED && !twiBaseAddress->EVENTS_ERROR); twiBaseAddress->EVENTS_RXSTARTED = 0x0UL; - while(!twiBaseAddress->EVENTS_LASTRX && !twiBaseAddress->EVENTS_ERROR); + txStartedCycleCount = DWT->CYCCNT; + uint32_t currentCycleCount; + while(!twiBaseAddress->EVENTS_LASTRX && !twiBaseAddress->EVENTS_ERROR) { + currentCycleCount = DWT->CYCCNT; + if ((currentCycleCount-txStartedCycleCount) > HwFreezedDelay) { + FixHwFreezed(); + return ErrorCodes::TransactionFailed; + } + } twiBaseAddress->EVENTS_LASTRX = 0x0UL; if (stop || twiBaseAddress->EVENTS_ERROR) { @@ -105,9 +142,10 @@ void TwiMaster::Read(uint8_t deviceAddress, uint8_t *buffer, size_t size, bool s if (twiBaseAddress->EVENTS_ERROR) { twiBaseAddress->EVENTS_ERROR = 0x0UL; } + return ErrorCodes::NoError; } -void TwiMaster::Write(uint8_t deviceAddress, const uint8_t *data, size_t size, bool stop) { +TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t *data, size_t size, bool stop) { twiBaseAddress->ADDRESS = deviceAddress; twiBaseAddress->TASKS_RESUME = 0x1UL; twiBaseAddress->TXD.PTR = (uint32_t)data; @@ -118,7 +156,15 @@ void TwiMaster::Write(uint8_t deviceAddress, const uint8_t *data, size_t size, b while(!twiBaseAddress->EVENTS_TXSTARTED && !twiBaseAddress->EVENTS_ERROR); twiBaseAddress->EVENTS_TXSTARTED = 0x0UL; - while(!twiBaseAddress->EVENTS_LASTTX && !twiBaseAddress->EVENTS_ERROR); + txStartedCycleCount = DWT->CYCCNT; + uint32_t currentCycleCount; + while(!twiBaseAddress->EVENTS_LASTTX && !twiBaseAddress->EVENTS_ERROR) { + currentCycleCount = DWT->CYCCNT; + if ((currentCycleCount-txStartedCycleCount) > HwFreezedDelay) { + FixHwFreezed(); + return ErrorCodes::TransactionFailed; + } + } twiBaseAddress->EVENTS_LASTTX = 0x0UL; if (stop || twiBaseAddress->EVENTS_ERROR) { @@ -137,4 +183,47 @@ void TwiMaster::Write(uint8_t deviceAddress, const uint8_t *data, size_t size, b uint32_t error = twiBaseAddress->ERRORSRC; twiBaseAddress->ERRORSRC = error; } -}
\ No newline at end of file + + return ErrorCodes::NoError; +} + +void TwiMaster::Sleep() { + while(twiBaseAddress->ENABLE != 0) { + twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos); + } + nrf_gpio_cfg_default(6); + nrf_gpio_cfg_default(7); + NRF_LOG_INFO("[TWIMASTER] Sleep"); +} + +void TwiMaster::Wakeup() { + Init(); + NRF_LOG_INFO("[TWIMASTER] Wakeup"); +} + +/* Sometimes, the TWIM device just freeze and never set the event EVENTS_LASTTX. + * This method disable and re-enable the peripheral so that it works again. + * This is just a workaround, and it would be better if we could find a way to prevent + * this issue from happening. + * */ +void TwiMaster::FixHwFreezed() { + NRF_LOG_INFO("I2C device frozen, reinitializing it!"); + // Disable I²C + uint32_t twi_state = NRF_TWI1->ENABLE; + twiBaseAddress->ENABLE = TWIM_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; + + NRF_GPIO->PIN_CNF[params.pinScl] = ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) + | ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) + | ((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) + | ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) + | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); + + NRF_GPIO->PIN_CNF[params.pinSda] = ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) + | ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) + | ((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) + | ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) + | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); + + // Re-enable I²C + twiBaseAddress->ENABLE = twi_state; +} diff --git a/src/drivers/TwiMaster.h b/src/drivers/TwiMaster.h index 3b7555f5..52e39098 100644 --- a/src/drivers/TwiMaster.h +++ b/src/drivers/TwiMaster.h @@ -10,6 +10,7 @@ namespace Pinetime { public: enum class Modules { TWIM1 }; enum class Frequencies {Khz100, Khz250, Khz400}; + enum class ErrorCodes {NoError, TransactionFailed}; struct Parameters { uint32_t frequency; uint8_t pinSda; @@ -19,12 +20,19 @@ namespace Pinetime { TwiMaster(const Modules module, const Parameters& params); void Init(); - void Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size); - void Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size); + ErrorCodes Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size); + ErrorCodes Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size); + + void Sleep(); + void Wakeup(); private: - void Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); - void Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); + ErrorCodes ReadWithRetry(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size); + ErrorCodes WriteWithRetry(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size); + + ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); + ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); + void FixHwFreezed(); NRF_TWIM_Type* twiBaseAddress; SemaphoreHandle_t mutex; const Modules module; @@ -32,7 +40,8 @@ namespace Pinetime { static constexpr uint8_t maxDataSize{8}; static constexpr uint8_t registerSize{1}; uint8_t internalBuffer[maxDataSize + registerSize]; - + uint32_t txStartedCycleCount = 0; + static constexpr uint32_t HwFreezedDelay{161000}; }; } }
\ No newline at end of file |
