aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Cst816s.cpp24
-rw-r--r--src/drivers/Cst816s.h14
-rw-r--r--src/drivers/Spi.cpp13
-rw-r--r--src/drivers/SpiMaster.cpp6
-rw-r--r--src/drivers/SpiNorFlash.cpp22
-rw-r--r--src/drivers/SpiNorFlash.h4
-rw-r--r--src/drivers/St7789.cpp6
-rw-r--r--src/drivers/TwiMaster.cpp111
-rw-r--r--src/drivers/TwiMaster.h19
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, &registerAddress, 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, &registerAddress, 1, false);
+ if(ret != ErrorCodes::NoError)
+ ret = Write(deviceAddress, &registerAddress, 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