Reformatted all the files according to clang-format style
This commit is contained in:
@@ -24,7 +24,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
Bma421::Bma421(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster{twiMaster}, deviceAddress{twiAddress} {
|
||||
Bma421::Bma421(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaster}, deviceAddress {twiAddress} {
|
||||
bma.intf = BMA4_I2C_INTF;
|
||||
bma.bus_read = user_i2c_read;
|
||||
bma.bus_write = user_i2c_write;
|
||||
@@ -35,25 +35,32 @@ Bma421::Bma421(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster{twiMaster},
|
||||
}
|
||||
|
||||
void Bma421::Init() {
|
||||
if(not isResetOk) return; // Call SoftReset (and reset TWI device) first!
|
||||
if (not isResetOk)
|
||||
return; // Call SoftReset (and reset TWI device) first!
|
||||
|
||||
auto ret = bma423_init(&bma);
|
||||
if(ret != BMA4_OK) return;
|
||||
if (ret != BMA4_OK)
|
||||
return;
|
||||
|
||||
ret = bma423_write_config_file(&bma);
|
||||
if(ret != BMA4_OK) return;
|
||||
if (ret != BMA4_OK)
|
||||
return;
|
||||
|
||||
ret = bma4_set_interrupt_mode(BMA4_LATCH_MODE, &bma);
|
||||
if(ret != BMA4_OK) return;
|
||||
if (ret != BMA4_OK)
|
||||
return;
|
||||
|
||||
ret = bma423_feature_enable(BMA423_STEP_CNTR, 1, &bma);
|
||||
if(ret != BMA4_OK) return;
|
||||
if (ret != BMA4_OK)
|
||||
return;
|
||||
|
||||
ret = bma423_step_detector_enable(0, &bma);
|
||||
if(ret != BMA4_OK) return;
|
||||
if (ret != BMA4_OK)
|
||||
return;
|
||||
|
||||
ret = bma4_set_accel_enable(1, &bma);
|
||||
if(ret != BMA4_OK) return;
|
||||
if (ret != BMA4_OK)
|
||||
return;
|
||||
|
||||
struct bma4_accel_config accel_conf;
|
||||
accel_conf.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
|
||||
@@ -61,7 +68,8 @@ void Bma421::Init() {
|
||||
accel_conf.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
|
||||
accel_conf.perf_mode = BMA4_CIC_AVG_MODE;
|
||||
ret = bma4_set_accel_config(&accel_conf, &bma);
|
||||
if(ret != BMA4_OK) return;
|
||||
if (ret != BMA4_OK)
|
||||
return;
|
||||
|
||||
isOk = true;
|
||||
}
|
||||
@@ -71,16 +79,17 @@ void Bma421::Reset() {
|
||||
twiMaster.Write(deviceAddress, 0x7E, &data, 1);
|
||||
}
|
||||
|
||||
void Bma421::Read(uint8_t registerAddress, uint8_t *buffer, size_t size) {
|
||||
void Bma421::Read(uint8_t registerAddress, uint8_t* buffer, size_t size) {
|
||||
twiMaster.Read(deviceAddress, registerAddress, buffer, size);
|
||||
}
|
||||
|
||||
void Bma421::Write(uint8_t registerAddress, const uint8_t *data, size_t size) {
|
||||
void Bma421::Write(uint8_t registerAddress, const uint8_t* data, size_t size) {
|
||||
twiMaster.Write(deviceAddress, registerAddress, data, size);
|
||||
}
|
||||
|
||||
Bma421::Values Bma421::Process() {
|
||||
if(not isOk) return {};
|
||||
if (not isOk)
|
||||
return {};
|
||||
struct bma4_accel data;
|
||||
bma4_read_accel_xyz(&data, &bma);
|
||||
|
||||
@@ -109,7 +118,7 @@ void Bma421::ResetStepCounter() {
|
||||
|
||||
void Bma421::SoftReset() {
|
||||
auto ret = bma4_soft_reset(&bma);
|
||||
if(ret == BMA4_OK) {
|
||||
if (ret == BMA4_OK) {
|
||||
isResetOk = true;
|
||||
nrf_delay_ms(1);
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class TwiMaster;
|
||||
class Bma421 {
|
||||
public:
|
||||
public:
|
||||
struct Values {
|
||||
uint32_t steps;
|
||||
int16_t x;
|
||||
@@ -25,12 +25,12 @@ namespace Pinetime {
|
||||
Values Process();
|
||||
void ResetStepCounter();
|
||||
|
||||
void Read(uint8_t registerAddress, uint8_t *buffer, size_t size);
|
||||
void Write(uint8_t registerAddress, const uint8_t *data, size_t size);
|
||||
void Read(uint8_t registerAddress, uint8_t* buffer, size_t size);
|
||||
void Write(uint8_t registerAddress, const uint8_t* data, size_t size);
|
||||
|
||||
bool IsOk() const;
|
||||
|
||||
private:
|
||||
private:
|
||||
void Reset();
|
||||
|
||||
TwiMaster& twiMaster;
|
||||
|
@@ -5,8 +5,8 @@
|
||||
namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class BufferProvider {
|
||||
public:
|
||||
virtual bool GetNextBuffer(uint8_t** buffer, size_t& size) = 0;
|
||||
public:
|
||||
virtual bool GetNextBuffer(uint8_t** buffer, size_t& size) = 0;
|
||||
};
|
||||
}
|
||||
}
|
@@ -7,14 +7,14 @@
|
||||
using namespace Pinetime::Drivers;
|
||||
|
||||
/* References :
|
||||
* This implementation is based on this article : https://medium.com/@ly.lee/building-a-rust-driver-for-pinetimes-touch-controller-cbc1a5d5d3e9
|
||||
* Touch panel datasheet (weird chinese translation) : https://wiki.pine64.org/images/5/51/CST816S%E6%95%B0%E6%8D%AE%E6%89%8B%E5%86%8CV1.1.en.pdf
|
||||
* This implementation is based on this article :
|
||||
* https://medium.com/@ly.lee/building-a-rust-driver-for-pinetimes-touch-controller-cbc1a5d5d3e9 Touch panel datasheet (weird chinese
|
||||
* translation) : https://wiki.pine64.org/images/5/51/CST816S%E6%95%B0%E6%8D%AE%E6%89%8B%E5%86%8CV1.1.en.pdf
|
||||
*
|
||||
* TODO : we need a complete datasheet and protocol reference!
|
||||
* */
|
||||
|
||||
Cst816S::Cst816S(TwiMaster &twiMaster, uint8_t twiAddress) : twiMaster{twiMaster}, twiAddress{twiAddress} {
|
||||
|
||||
Cst816S::Cst816S(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaster}, twiAddress {twiAddress} {
|
||||
}
|
||||
|
||||
void Cst816S::Init() {
|
||||
@@ -32,7 +32,7 @@ void Cst816S::Init() {
|
||||
vTaskDelay(5);
|
||||
twiMaster.Read(twiAddress, 0xa7, &dummy, 1);
|
||||
vTaskDelay(5);
|
||||
|
||||
|
||||
/*
|
||||
[2] EnConLR - Continuous operation can slide around
|
||||
[1] EnConUD - Slide up and down to enable continuous operation
|
||||
@@ -40,23 +40,22 @@ void Cst816S::Init() {
|
||||
*/
|
||||
static constexpr uint8_t motionMask = 0b00000101;
|
||||
twiMaster.Write(twiAddress, 0xEC, &motionMask, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Cst816S::TouchInfos Cst816S::GetTouchInfo() {
|
||||
Cst816S::TouchInfos info;
|
||||
|
||||
auto ret = twiMaster.Read(twiAddress, 0, touchData, sizeof(touchData));
|
||||
if(ret != TwiMaster::ErrorCodes::NoError) return {};
|
||||
if (ret != TwiMaster::ErrorCodes::NoError)
|
||||
return {};
|
||||
|
||||
auto nbTouchPoints = touchData[2] & 0x0f;
|
||||
|
||||
uint8_t i = 0;
|
||||
|
||||
uint8_t pointId = (touchData[touchIdIndex + (touchStep * i)]) >> 4;
|
||||
if(nbTouchPoints == 0 && pointId == lastTouchId) return info;
|
||||
|
||||
if (nbTouchPoints == 0 && pointId == lastTouchId)
|
||||
return info;
|
||||
|
||||
info.isTouch = true;
|
||||
|
||||
|
@@ -5,57 +5,58 @@
|
||||
namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class Cst816S {
|
||||
public :
|
||||
enum class Gestures : uint8_t {
|
||||
None = 0x00,
|
||||
SlideDown = 0x01,
|
||||
SlideUp = 0x02,
|
||||
SlideLeft = 0x03,
|
||||
SlideRight = 0x04,
|
||||
SingleTap = 0x05,
|
||||
DoubleTap = 0x0B,
|
||||
LongPress = 0x0C
|
||||
};
|
||||
struct TouchInfos {
|
||||
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;
|
||||
};
|
||||
public:
|
||||
enum class Gestures : uint8_t {
|
||||
None = 0x00,
|
||||
SlideDown = 0x01,
|
||||
SlideUp = 0x02,
|
||||
SlideLeft = 0x03,
|
||||
SlideRight = 0x04,
|
||||
SingleTap = 0x05,
|
||||
DoubleTap = 0x0B,
|
||||
LongPress = 0x0C
|
||||
};
|
||||
struct TouchInfos {
|
||||
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;
|
||||
};
|
||||
|
||||
Cst816S(TwiMaster& twiMaster, uint8_t twiAddress);
|
||||
Cst816S(const Cst816S&) = delete;
|
||||
Cst816S& operator=(const Cst816S&) = delete;
|
||||
Cst816S(Cst816S&&) = delete;
|
||||
Cst816S& operator=(Cst816S&&) = delete;
|
||||
Cst816S(TwiMaster& twiMaster, uint8_t twiAddress);
|
||||
Cst816S(const Cst816S&) = delete;
|
||||
Cst816S& operator=(const Cst816S&) = delete;
|
||||
Cst816S(Cst816S&&) = delete;
|
||||
Cst816S& operator=(Cst816S&&) = delete;
|
||||
|
||||
void Init();
|
||||
TouchInfos GetTouchInfo();
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
private:
|
||||
static constexpr uint8_t pinIrq = 28;
|
||||
static constexpr uint8_t pinReset = 10;
|
||||
static constexpr uint8_t lastTouchId = 0x0f;
|
||||
static constexpr uint8_t touchPointNumIndex = 2;
|
||||
static constexpr uint8_t touchMiscIndex = 8;
|
||||
static constexpr uint8_t touchXYIndex = 7;
|
||||
static constexpr uint8_t touchEventIndex = 3;
|
||||
static constexpr uint8_t touchXHighIndex = 3;
|
||||
static constexpr uint8_t touchXLowIndex = 4;
|
||||
static constexpr uint8_t touchYHighIndex = 5;
|
||||
static constexpr uint8_t touchYLowIndex = 6;
|
||||
static constexpr uint8_t touchIdIndex = 5;
|
||||
static constexpr uint8_t touchStep = 6;
|
||||
static constexpr uint8_t gestureIndex = 1;
|
||||
void Init();
|
||||
TouchInfos GetTouchInfo();
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
|
||||
uint8_t touchData[10];
|
||||
TwiMaster& twiMaster;
|
||||
uint8_t twiAddress;
|
||||
private:
|
||||
static constexpr uint8_t pinIrq = 28;
|
||||
static constexpr uint8_t pinReset = 10;
|
||||
static constexpr uint8_t lastTouchId = 0x0f;
|
||||
static constexpr uint8_t touchPointNumIndex = 2;
|
||||
static constexpr uint8_t touchMiscIndex = 8;
|
||||
static constexpr uint8_t touchXYIndex = 7;
|
||||
static constexpr uint8_t touchEventIndex = 3;
|
||||
static constexpr uint8_t touchXHighIndex = 3;
|
||||
static constexpr uint8_t touchXLowIndex = 4;
|
||||
static constexpr uint8_t touchYHighIndex = 5;
|
||||
static constexpr uint8_t touchYLowIndex = 6;
|
||||
static constexpr uint8_t touchIdIndex = 5;
|
||||
static constexpr uint8_t touchStep = 6;
|
||||
static constexpr uint8_t gestureIndex = 1;
|
||||
|
||||
uint8_t touchData[10];
|
||||
TwiMaster& twiMaster;
|
||||
uint8_t twiAddress;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -19,31 +19,27 @@ void debugpins_init() {
|
||||
nrf_gpio_pin_clear(DebugPin4);
|
||||
}
|
||||
void debugpins_set(debugpins_pins pin) {
|
||||
nrf_gpio_pin_set((uint32_t)(pin));
|
||||
nrf_gpio_pin_set((uint32_t) (pin));
|
||||
}
|
||||
|
||||
void debugpins_clear(debugpins_pins pin) {
|
||||
nrf_gpio_pin_clear((uint32_t)(pin));
|
||||
nrf_gpio_pin_clear((uint32_t) (pin));
|
||||
}
|
||||
|
||||
void debugpins_pulse(debugpins_pins pin) {
|
||||
nrf_gpio_pin_set((uint32_t)(pin));
|
||||
nrf_gpio_pin_clear((uint32_t)(pin));
|
||||
nrf_gpio_pin_set((uint32_t) (pin));
|
||||
nrf_gpio_pin_clear((uint32_t) (pin));
|
||||
}
|
||||
#else
|
||||
void debugpins_init() {
|
||||
|
||||
}
|
||||
void debugpins_set(debugpins_pins pin) {
|
||||
|
||||
}
|
||||
|
||||
void debugpins_clear(debugpins_pins pin) {
|
||||
|
||||
}
|
||||
|
||||
void debugpins_pulse(debugpins_pins pin) {
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -22,4 +22,3 @@ void debugpins_pulse(debugpins_pins pin);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -16,8 +16,7 @@ using namespace Pinetime::Drivers;
|
||||
/** Driver for the HRS3300 heart rate sensor.
|
||||
* Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/drivers/hrs3300.py
|
||||
*/
|
||||
Hrs3300::Hrs3300(TwiMaster &twiMaster, uint8_t twiAddress) : twiMaster{twiMaster}, twiAddress{twiAddress} {
|
||||
|
||||
Hrs3300::Hrs3300(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaster}, twiAddress {twiAddress} {
|
||||
}
|
||||
|
||||
void Hrs3300::Init() {
|
||||
@@ -73,7 +72,7 @@ void Hrs3300::SetGain(uint8_t gain) {
|
||||
constexpr uint8_t maxGain = 64U;
|
||||
gain = std::min(gain, maxGain);
|
||||
uint8_t hgain = 0;
|
||||
while((1 << hgain) < gain){
|
||||
while ((1 << hgain) < gain) {
|
||||
++hgain;
|
||||
}
|
||||
|
||||
@@ -93,25 +92,14 @@ void Hrs3300::SetDrive(uint8_t drive) {
|
||||
|
||||
void Hrs3300::WriteRegister(uint8_t reg, uint8_t data) {
|
||||
auto ret = twiMaster.Write(twiAddress, reg, &data, 1);
|
||||
if(ret != TwiMaster::ErrorCodes::NoError)
|
||||
if (ret != TwiMaster::ErrorCodes::NoError)
|
||||
NRF_LOG_INFO("WRITE ERROR");
|
||||
}
|
||||
|
||||
uint8_t Hrs3300::ReadRegister(uint8_t reg) {
|
||||
uint8_t value;
|
||||
auto ret = twiMaster.Read(twiAddress, reg, &value, 1);
|
||||
if(ret != TwiMaster::ErrorCodes::NoError)
|
||||
if (ret != TwiMaster::ErrorCodes::NoError)
|
||||
NRF_LOG_INFO("READ ERROR");
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class Hrs3300 {
|
||||
public:
|
||||
public:
|
||||
enum class Registers : uint8_t {
|
||||
Id = 0x00,
|
||||
Enable = 0x01,
|
||||
@@ -35,13 +35,12 @@ namespace Pinetime {
|
||||
void SetGain(uint8_t gain);
|
||||
void SetDrive(uint8_t drive);
|
||||
|
||||
private:
|
||||
private:
|
||||
TwiMaster& twiMaster;
|
||||
uint8_t twiAddress;
|
||||
|
||||
void WriteRegister(uint8_t reg, uint8_t data);
|
||||
uint8_t ReadRegister(uint8_t reg);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ void InternalFlash::WriteWord(uint32_t address, uint32_t value) {
|
||||
__DSB();
|
||||
|
||||
// Write word
|
||||
*(uint32_t*)address = value;
|
||||
*(uint32_t*) address = value;
|
||||
Wait();
|
||||
|
||||
// Disable write
|
||||
@@ -35,5 +35,7 @@ void InternalFlash::WriteWord(uint32_t address, uint32_t value) {
|
||||
}
|
||||
|
||||
void InternalFlash::Wait() {
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;}
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@@ -5,10 +5,11 @@
|
||||
namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class InternalFlash {
|
||||
public:
|
||||
public:
|
||||
static void ErasePage(uint32_t address);
|
||||
static void WriteWord(uint32_t address, uint32_t value);
|
||||
private:
|
||||
|
||||
private:
|
||||
static inline void Wait();
|
||||
};
|
||||
}
|
||||
|
@@ -4,17 +4,16 @@
|
||||
|
||||
using namespace Pinetime::Drivers;
|
||||
|
||||
Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) :
|
||||
spiMaster{spiMaster}, pinCsn{pinCsn} {
|
||||
Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) : spiMaster {spiMaster}, pinCsn {pinCsn} {
|
||||
nrf_gpio_cfg_output(pinCsn);
|
||||
nrf_gpio_pin_set(pinCsn);
|
||||
}
|
||||
|
||||
bool Spi::Write(const uint8_t *data, size_t size) {
|
||||
bool Spi::Write(const uint8_t* data, size_t size) {
|
||||
return spiMaster.Write(pinCsn, data, size);
|
||||
}
|
||||
|
||||
bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize) {
|
||||
bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) {
|
||||
return spiMaster.Read(pinCsn, cmd, cmdSize, data, dataSize);
|
||||
}
|
||||
|
||||
@@ -23,7 +22,7 @@ void Spi::Sleep() {
|
||||
NRF_LOG_INFO("[SPI] Sleep")
|
||||
}
|
||||
|
||||
bool Spi::WriteCmdAndBuffer(const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -37,5 +36,3 @@ void Spi::Wakeup() {
|
||||
nrf_gpio_pin_set(pinCsn);
|
||||
NRF_LOG_INFO("[SPI] Wakeup")
|
||||
}
|
||||
|
||||
|
||||
|
@@ -6,23 +6,23 @@
|
||||
namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class Spi {
|
||||
public:
|
||||
Spi(SpiMaster& spiMaster, uint8_t pinCsn);
|
||||
Spi(const Spi&) = delete;
|
||||
Spi& operator=(const Spi&) = delete;
|
||||
Spi(Spi&&) = delete;
|
||||
Spi& operator=(Spi&&) = delete;
|
||||
public:
|
||||
Spi(SpiMaster& spiMaster, uint8_t pinCsn);
|
||||
Spi(const Spi&) = delete;
|
||||
Spi& operator=(const Spi&) = delete;
|
||||
Spi(Spi&&) = delete;
|
||||
Spi& operator=(Spi&&) = delete;
|
||||
|
||||
bool Init();
|
||||
bool Write(const uint8_t* data, size_t size);
|
||||
bool Read(uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize);
|
||||
bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t *data, size_t dataSize);
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
bool Init();
|
||||
bool Write(const uint8_t* data, size_t size);
|
||||
bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize);
|
||||
bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize);
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
|
||||
private:
|
||||
SpiMaster& spiMaster;
|
||||
uint8_t pinCsn;
|
||||
private:
|
||||
SpiMaster& spiMaster;
|
||||
uint8_t pinCsn;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -6,8 +6,7 @@
|
||||
|
||||
using namespace Pinetime::Drivers;
|
||||
|
||||
SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters ¶ms) :
|
||||
spi{spi}, params{params} {
|
||||
SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters& params) : spi {spi}, params {params} {
|
||||
mutex = xSemaphoreCreateBinary();
|
||||
ASSERT(mutex != NULL);
|
||||
}
|
||||
@@ -19,39 +18,58 @@ bool SpiMaster::Init() {
|
||||
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;
|
||||
// nrf_gpio_cfg_output(params.pinCSN);
|
||||
// pinCsn = params.pinCSN;
|
||||
|
||||
switch(spi) {
|
||||
case SpiModule::SPI0: spiBaseAddress = NRF_SPIM0; break;
|
||||
case SpiModule::SPI1: spiBaseAddress = NRF_SPIM1; break;
|
||||
default: return false;
|
||||
switch (spi) {
|
||||
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->PSELSCK = params.pinSCK;
|
||||
spiBaseAddress->PSELMOSI = params.pinMOSI;
|
||||
spiBaseAddress->PSELMISO = params.pinMISO;
|
||||
|
||||
uint32_t frequency;
|
||||
switch(params.Frequency) {
|
||||
case Frequencies::Freq8Mhz: frequency = 0x80000000; break;
|
||||
default: return false;
|
||||
switch (params.Frequency) {
|
||||
case Frequencies::Freq8Mhz:
|
||||
frequency = 0x80000000;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
spiBaseAddress->FREQUENCY = frequency;
|
||||
|
||||
uint32_t regConfig = 0;
|
||||
switch(params.bitOrder) {
|
||||
case BitOrder::Msb_Lsb: break;
|
||||
case BitOrder::Lsb_Msb: regConfig = 1;
|
||||
default: return false;
|
||||
switch (params.bitOrder) {
|
||||
case BitOrder::Msb_Lsb:
|
||||
break;
|
||||
case BitOrder::Lsb_Msb:
|
||||
regConfig = 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch(params.mode) {
|
||||
case Modes::Mode0: break;
|
||||
case Modes::Mode1: regConfig |= (0x01 << 1); break;
|
||||
case Modes::Mode2: regConfig |= (0x02 << 1); break;
|
||||
case Modes::Mode3: regConfig |= (0x03 << 1); break;
|
||||
default: return false;
|
||||
switch (params.mode) {
|
||||
case Modes::Mode0:
|
||||
break;
|
||||
case Modes::Mode1:
|
||||
regConfig |= (0x01 << 1);
|
||||
break;
|
||||
case Modes::Mode2:
|
||||
regConfig |= (0x02 << 1);
|
||||
break;
|
||||
case Modes::Mode3:
|
||||
regConfig |= (0x03 << 1);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
spiBaseAddress->CONFIG = regConfig;
|
||||
@@ -59,24 +77,22 @@ bool SpiMaster::Init() {
|
||||
spiBaseAddress->EVENTS_ENDTX = 0;
|
||||
spiBaseAddress->EVENTS_END = 0;
|
||||
|
||||
spiBaseAddress->INTENSET = ((unsigned)1 << (unsigned)6);
|
||||
spiBaseAddress->INTENSET = ((unsigned)1 << (unsigned)1);
|
||||
spiBaseAddress->INTENSET = ((unsigned)1 << (unsigned)19);
|
||||
spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 6);
|
||||
spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 1);
|
||||
spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 19);
|
||||
|
||||
spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos);
|
||||
|
||||
NRFX_IRQ_PRIORITY_SET(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn,2);
|
||||
NRFX_IRQ_PRIORITY_SET(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 2);
|
||||
NRFX_IRQ_ENABLE(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn);
|
||||
|
||||
xSemaphoreGive(mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SpiMaster::SetupWorkaroundForFtpan58(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) |
|
||||
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.
|
||||
@@ -86,29 +102,29 @@ void SpiMaster::SetupWorkaroundForFtpan58(NRF_SPIM_Type *spim, uint32_t ppi_chan
|
||||
spiBaseAddress->EVENTS_END = 0;
|
||||
|
||||
// Disable IRQ
|
||||
spim->INTENCLR = (1<<6);
|
||||
spim->INTENCLR = (1<<1);
|
||||
spim->INTENCLR = (1<<19);
|
||||
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) {
|
||||
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;
|
||||
spiBaseAddress->EVENTS_END = 0;
|
||||
spim->INTENSET = (1<<6);
|
||||
spim->INTENSET = (1<<1);
|
||||
spim->INTENSET = (1<<19);
|
||||
spim->INTENSET = (1 << 6);
|
||||
spim->INTENSET = (1 << 1);
|
||||
spim->INTENSET = (1 << 19);
|
||||
}
|
||||
|
||||
void SpiMaster::OnEndEvent() {
|
||||
if(currentBufferAddr == 0) {
|
||||
if (currentBufferAddr == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto s = currentBufferSize;
|
||||
if(s > 0) {
|
||||
if (s > 0) {
|
||||
auto currentSize = std::min((size_t) 255, s);
|
||||
PrepareTx(currentBufferAddr, currentSize);
|
||||
currentBufferAddr += currentSize;
|
||||
@@ -116,17 +132,17 @@ void SpiMaster::OnEndEvent() {
|
||||
|
||||
spiBaseAddress->TASKS_START = 1;
|
||||
} else {
|
||||
if(taskToNotify != nullptr) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
nrf_gpio_pin_set(this->pinCsn);
|
||||
currentBufferAddr = 0;
|
||||
if (taskToNotify != nullptr) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken);
|
||||
vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
nrf_gpio_pin_set(this->pinCsn);
|
||||
currentBufferAddr = 0;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +159,10 @@ void SpiMaster::PrepareTx(const volatile uint32_t bufferAddress, const volatile
|
||||
spiBaseAddress->EVENTS_END = 0;
|
||||
}
|
||||
|
||||
void SpiMaster::PrepareRx(const volatile uint32_t cmdAddress, const volatile size_t cmdSize, const volatile uint32_t bufferAddress, const volatile size_t size) {
|
||||
void SpiMaster::PrepareRx(const volatile uint32_t cmdAddress,
|
||||
const volatile size_t cmdSize,
|
||||
const volatile uint32_t bufferAddress,
|
||||
const volatile size_t size) {
|
||||
spiBaseAddress->TXD.PTR = 0;
|
||||
spiBaseAddress->TXD.MAXCNT = 0;
|
||||
spiBaseAddress->TXD.LIST = 0;
|
||||
@@ -153,35 +172,35 @@ void SpiMaster::PrepareRx(const volatile uint32_t cmdAddress, const volatile siz
|
||||
spiBaseAddress->EVENTS_END = 0;
|
||||
}
|
||||
|
||||
|
||||
bool SpiMaster::Write(uint8_t pinCsn, const uint8_t *data, size_t size) {
|
||||
if(data == nullptr) return false;
|
||||
bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) {
|
||||
if (data == nullptr)
|
||||
return false;
|
||||
auto ok = xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
ASSERT(ok == true);
|
||||
taskToNotify = xTaskGetCurrentTaskHandle();
|
||||
|
||||
|
||||
this->pinCsn = pinCsn;
|
||||
|
||||
if(size == 1) {
|
||||
SetupWorkaroundForFtpan58(spiBaseAddress, 0,0);
|
||||
if (size == 1) {
|
||||
SetupWorkaroundForFtpan58(spiBaseAddress, 0, 0);
|
||||
} else {
|
||||
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
|
||||
}
|
||||
|
||||
nrf_gpio_pin_clear(this->pinCsn);
|
||||
|
||||
currentBufferAddr = (uint32_t)data;
|
||||
currentBufferAddr = (uint32_t) data;
|
||||
currentBufferSize = size;
|
||||
|
||||
auto currentSize = std::min((size_t)255, (size_t)currentBufferSize);
|
||||
auto currentSize = std::min((size_t) 255, (size_t) currentBufferSize);
|
||||
PrepareTx(currentBufferAddr, currentSize);
|
||||
currentBufferSize -= currentSize;
|
||||
currentBufferAddr += currentSize;
|
||||
spiBaseAddress->TASKS_START = 1;
|
||||
|
||||
if(size == 1) {
|
||||
while (spiBaseAddress->EVENTS_END == 0);
|
||||
if (size == 1) {
|
||||
while (spiBaseAddress->EVENTS_END == 0)
|
||||
;
|
||||
nrf_gpio_pin_set(this->pinCsn);
|
||||
currentBufferAddr = 0;
|
||||
xSemaphoreGive(mutex);
|
||||
@@ -190,41 +209,41 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t *data, size_t size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpiMaster::Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize) {
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
bool SpiMaster::Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) {
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
|
||||
taskToNotify = nullptr;
|
||||
taskToNotify = nullptr;
|
||||
|
||||
this->pinCsn = pinCsn;
|
||||
DisableWorkaroundForFtpan58(spiBaseAddress, 0,0);
|
||||
spiBaseAddress->INTENCLR = (1<<6);
|
||||
spiBaseAddress->INTENCLR = (1<<1);
|
||||
spiBaseAddress->INTENCLR = (1<<19);
|
||||
this->pinCsn = pinCsn;
|
||||
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
|
||||
spiBaseAddress->INTENCLR = (1 << 6);
|
||||
spiBaseAddress->INTENCLR = (1 << 1);
|
||||
spiBaseAddress->INTENCLR = (1 << 19);
|
||||
|
||||
nrf_gpio_pin_clear(this->pinCsn);
|
||||
nrf_gpio_pin_clear(this->pinCsn);
|
||||
|
||||
currentBufferAddr = 0;
|
||||
currentBufferSize = 0;
|
||||
|
||||
currentBufferAddr = 0;
|
||||
currentBufferSize = 0;
|
||||
PrepareTx((uint32_t) cmd, cmdSize);
|
||||
spiBaseAddress->TASKS_START = 1;
|
||||
while (spiBaseAddress->EVENTS_END == 0)
|
||||
;
|
||||
|
||||
PrepareTx((uint32_t)cmd, cmdSize);
|
||||
spiBaseAddress->TASKS_START = 1;
|
||||
while (spiBaseAddress->EVENTS_END == 0);
|
||||
PrepareRx((uint32_t) cmd, cmdSize, (uint32_t) data, dataSize);
|
||||
spiBaseAddress->TASKS_START = 1;
|
||||
|
||||
PrepareRx((uint32_t)cmd, cmdSize, (uint32_t)data, dataSize);
|
||||
spiBaseAddress->TASKS_START = 1;
|
||||
while (spiBaseAddress->EVENTS_END == 0)
|
||||
;
|
||||
nrf_gpio_pin_set(this->pinCsn);
|
||||
|
||||
while (spiBaseAddress->EVENTS_END == 0);
|
||||
nrf_gpio_pin_set(this->pinCsn);
|
||||
xSemaphoreGive(mutex);
|
||||
|
||||
xSemaphoreGive(mutex);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SpiMaster::Sleep() {
|
||||
while(spiBaseAddress->ENABLE != 0) {
|
||||
while (spiBaseAddress->ENABLE != 0) {
|
||||
spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos);
|
||||
}
|
||||
nrf_gpio_cfg_default(params.pinSCK);
|
||||
@@ -239,37 +258,35 @@ void SpiMaster::Wakeup() {
|
||||
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) {
|
||||
bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) {
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
|
||||
taskToNotify = nullptr;
|
||||
|
||||
this->pinCsn = pinCsn;
|
||||
DisableWorkaroundForFtpan58(spiBaseAddress, 0,0);
|
||||
spiBaseAddress->INTENCLR = (1<<6);
|
||||
spiBaseAddress->INTENCLR = (1<<1);
|
||||
spiBaseAddress->INTENCLR = (1<<19);
|
||||
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
|
||||
spiBaseAddress->INTENCLR = (1 << 6);
|
||||
spiBaseAddress->INTENCLR = (1 << 1);
|
||||
spiBaseAddress->INTENCLR = (1 << 19);
|
||||
|
||||
nrf_gpio_pin_clear(this->pinCsn);
|
||||
|
||||
|
||||
currentBufferAddr = 0;
|
||||
currentBufferSize = 0;
|
||||
|
||||
PrepareTx((uint32_t)cmd, cmdSize);
|
||||
PrepareTx((uint32_t) cmd, cmdSize);
|
||||
spiBaseAddress->TASKS_START = 1;
|
||||
while (spiBaseAddress->EVENTS_END == 0);
|
||||
while (spiBaseAddress->EVENTS_END == 0)
|
||||
;
|
||||
|
||||
PrepareTx((uint32_t)data, dataSize);
|
||||
PrepareTx((uint32_t) data, dataSize);
|
||||
spiBaseAddress->TASKS_START = 1;
|
||||
|
||||
while (spiBaseAddress->EVENTS_END == 0);
|
||||
while (spiBaseAddress->EVENTS_END == 0)
|
||||
;
|
||||
nrf_gpio_pin_set(this->pinCsn);
|
||||
|
||||
xSemaphoreGive(mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -9,54 +9,58 @@
|
||||
namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class SpiMaster {
|
||||
public:;
|
||||
enum class SpiModule : uint8_t {SPI0, SPI1};
|
||||
enum class BitOrder : uint8_t {Msb_Lsb, Lsb_Msb};
|
||||
enum class Modes : uint8_t {Mode0, Mode1, Mode2, Mode3};
|
||||
enum class Frequencies : uint8_t {Freq8Mhz};
|
||||
struct Parameters {
|
||||
BitOrder bitOrder;
|
||||
Modes mode;
|
||||
Frequencies Frequency;
|
||||
uint8_t pinSCK;
|
||||
uint8_t pinMOSI;
|
||||
uint8_t pinMISO;
|
||||
};
|
||||
public:
|
||||
;
|
||||
enum class SpiModule : uint8_t { SPI0, SPI1 };
|
||||
enum class BitOrder : uint8_t { Msb_Lsb, Lsb_Msb };
|
||||
enum class Modes : uint8_t { Mode0, Mode1, Mode2, Mode3 };
|
||||
enum class Frequencies : uint8_t { Freq8Mhz };
|
||||
struct Parameters {
|
||||
BitOrder bitOrder;
|
||||
Modes mode;
|
||||
Frequencies Frequency;
|
||||
uint8_t pinSCK;
|
||||
uint8_t pinMOSI;
|
||||
uint8_t pinMISO;
|
||||
};
|
||||
|
||||
SpiMaster(const SpiModule spi, const Parameters& params);
|
||||
SpiMaster(const SpiMaster&) = delete;
|
||||
SpiMaster& operator=(const SpiMaster&) = delete;
|
||||
SpiMaster(SpiMaster&&) = delete;
|
||||
SpiMaster& operator=(SpiMaster&&) = delete;
|
||||
SpiMaster(const SpiModule spi, const Parameters& params);
|
||||
SpiMaster(const SpiMaster&) = delete;
|
||||
SpiMaster& operator=(const SpiMaster&) = delete;
|
||||
SpiMaster(SpiMaster&&) = delete;
|
||||
SpiMaster& operator=(SpiMaster&&) = delete;
|
||||
|
||||
bool Init();
|
||||
bool Write(uint8_t pinCsn, const uint8_t* data, size_t size);
|
||||
bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize);
|
||||
bool Init();
|
||||
bool Write(uint8_t pinCsn, const uint8_t* data, size_t size);
|
||||
bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize);
|
||||
|
||||
bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t *data, size_t dataSize);
|
||||
bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize);
|
||||
|
||||
void OnStartedEvent();
|
||||
void OnEndEvent();
|
||||
void OnStartedEvent();
|
||||
void OnEndEvent();
|
||||
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
|
||||
private:
|
||||
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);
|
||||
void PrepareRx(const volatile uint32_t cmdAddress, const volatile size_t cmdSize, const volatile uint32_t bufferAddress, const volatile size_t size);
|
||||
private:
|
||||
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);
|
||||
void PrepareRx(const volatile uint32_t cmdAddress,
|
||||
const volatile size_t cmdSize,
|
||||
const volatile uint32_t bufferAddress,
|
||||
const volatile size_t size);
|
||||
|
||||
NRF_SPIM_Type * spiBaseAddress;
|
||||
uint8_t pinCsn;
|
||||
NRF_SPIM_Type* spiBaseAddress;
|
||||
uint8_t pinCsn;
|
||||
|
||||
SpiMaster::SpiModule spi;
|
||||
SpiMaster::Parameters params;
|
||||
SpiMaster::SpiModule spi;
|
||||
SpiMaster::Parameters params;
|
||||
|
||||
volatile uint32_t currentBufferAddr = 0;
|
||||
volatile size_t currentBufferSize = 0;
|
||||
volatile TaskHandle_t taskToNotify;
|
||||
SemaphoreHandle_t mutex;
|
||||
volatile uint32_t currentBufferAddr = 0;
|
||||
volatile size_t currentBufferSize = 0;
|
||||
volatile TaskHandle_t taskToNotify;
|
||||
SemaphoreHandle_t mutex;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -6,17 +6,16 @@
|
||||
|
||||
using namespace Pinetime::Drivers;
|
||||
|
||||
SpiNorFlash::SpiNorFlash(Spi& spi) : spi{spi} {
|
||||
|
||||
SpiNorFlash::SpiNorFlash(Spi& spi) : spi {spi} {
|
||||
}
|
||||
|
||||
void SpiNorFlash::Init() {
|
||||
device_id = ReadIdentificaion();
|
||||
NRF_LOG_INFO("[SpiNorFlash] Manufacturer : %d, Memory type : %d, memory density : %d", device_id.manufacturer, device_id.type, device_id.density);
|
||||
NRF_LOG_INFO(
|
||||
"[SpiNorFlash] Manufacturer : %d, Memory type : %d, memory density : %d", device_id.manufacturer, device_id.type, device_id.density);
|
||||
}
|
||||
|
||||
void SpiNorFlash::Uninit() {
|
||||
|
||||
}
|
||||
|
||||
void SpiNorFlash::Sleep() {
|
||||
@@ -30,12 +29,11 @@ void SpiNorFlash::Wakeup() {
|
||||
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) {
|
||||
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 {
|
||||
} else {
|
||||
NRF_LOG_INFO("[SpiNorFlash] ID on Wakeup: %d", id);
|
||||
}
|
||||
NRF_LOG_INFO("[SpiNorFlash] Wakeup")
|
||||
@@ -44,7 +42,7 @@ void SpiNorFlash::Wakeup() {
|
||||
SpiNorFlash::Identification SpiNorFlash::ReadIdentificaion() {
|
||||
auto cmd = static_cast<uint8_t>(Commands::ReadIdentification);
|
||||
Identification identification;
|
||||
spi.Read(&cmd, 1, reinterpret_cast<uint8_t *>(&identification), sizeof(Identification));
|
||||
spi.Read(&cmd, 1, reinterpret_cast<uint8_t*>(&identification), sizeof(Identification));
|
||||
return identification;
|
||||
}
|
||||
|
||||
@@ -70,11 +68,10 @@ uint8_t SpiNorFlash::ReadConfigurationRegister() {
|
||||
return status;
|
||||
}
|
||||
|
||||
void SpiNorFlash::Read(uint32_t address, uint8_t *buffer, size_t size) {
|
||||
void SpiNorFlash::Read(uint32_t address, uint8_t* buffer, size_t size) {
|
||||
static constexpr uint8_t cmdSize = 4;
|
||||
uint8_t cmd[cmdSize] = { static_cast<uint8_t>(Commands::Read), (uint8_t)(address >> 16U), (uint8_t)(address >> 8U),
|
||||
(uint8_t)address };
|
||||
spi.Read(reinterpret_cast<uint8_t *>(&cmd), cmdSize, buffer, size);
|
||||
uint8_t cmd[cmdSize] = {static_cast<uint8_t>(Commands::Read), (uint8_t) (address >> 16U), (uint8_t) (address >> 8U), (uint8_t) address};
|
||||
spi.Read(reinterpret_cast<uint8_t*>(&cmd), cmdSize, buffer, size);
|
||||
}
|
||||
|
||||
void SpiNorFlash::WriteEnable() {
|
||||
@@ -84,15 +81,19 @@ void SpiNorFlash::WriteEnable() {
|
||||
|
||||
void SpiNorFlash::SectorErase(uint32_t sectorAddress) {
|
||||
static constexpr uint8_t cmdSize = 4;
|
||||
uint8_t cmd[cmdSize] = { static_cast<uint8_t>(Commands::SectorErase), (uint8_t)(sectorAddress >> 16U), (uint8_t)(sectorAddress >> 8U),
|
||||
(uint8_t)sectorAddress };
|
||||
uint8_t cmd[cmdSize] = {static_cast<uint8_t>(Commands::SectorErase),
|
||||
(uint8_t) (sectorAddress >> 16U),
|
||||
(uint8_t) (sectorAddress >> 8U),
|
||||
(uint8_t) sectorAddress};
|
||||
|
||||
WriteEnable();
|
||||
while(!WriteEnabled()) vTaskDelay(1);
|
||||
while (!WriteEnabled())
|
||||
vTaskDelay(1);
|
||||
|
||||
spi.Read(reinterpret_cast<uint8_t *>(&cmd), cmdSize, nullptr, 0);
|
||||
spi.Read(reinterpret_cast<uint8_t*>(&cmd), cmdSize, nullptr, 0);
|
||||
|
||||
while(WriteInProgress()) vTaskDelay(1);
|
||||
while (WriteInProgress())
|
||||
vTaskDelay(1);
|
||||
}
|
||||
|
||||
uint8_t SpiNorFlash::ReadSecurityRegister() {
|
||||
@@ -110,29 +111,29 @@ bool SpiNorFlash::EraseFailed() {
|
||||
return (ReadSecurityRegister() & 0x40u) == 0x40u;
|
||||
}
|
||||
|
||||
void SpiNorFlash::Write(uint32_t address, const uint8_t *buffer, size_t size) {
|
||||
void SpiNorFlash::Write(uint32_t address, const uint8_t* buffer, size_t size) {
|
||||
static constexpr uint8_t cmdSize = 4;
|
||||
|
||||
size_t len = size;
|
||||
uint32_t addr = address;
|
||||
const uint8_t* b = buffer;
|
||||
while(len > 0) {
|
||||
while (len > 0) {
|
||||
uint32_t pageLimit = (addr & ~(pageSize - 1u)) + pageSize;
|
||||
uint32_t toWrite = pageLimit - addr > len ? len : pageLimit - addr;
|
||||
uint32_t toWrite = pageLimit - addr > len ? len : pageLimit - addr;
|
||||
|
||||
uint8_t cmd[cmdSize] = { static_cast<uint8_t>(Commands::PageProgram), (uint8_t)(addr >> 16U), (uint8_t)(addr >> 8U),
|
||||
(uint8_t)addr };
|
||||
uint8_t cmd[cmdSize] = {static_cast<uint8_t>(Commands::PageProgram), (uint8_t) (addr >> 16U), (uint8_t) (addr >> 8U), (uint8_t) addr};
|
||||
|
||||
WriteEnable();
|
||||
while(!WriteEnabled()) vTaskDelay(1);
|
||||
while (!WriteEnabled())
|
||||
vTaskDelay(1);
|
||||
|
||||
spi.WriteCmdAndBuffer(cmd, cmdSize, b, toWrite);
|
||||
|
||||
while(WriteInProgress()) vTaskDelay(1);
|
||||
while (WriteInProgress())
|
||||
vTaskDelay(1);
|
||||
|
||||
addr += toWrite;
|
||||
b += toWrite;
|
||||
len -= toWrite;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,58 +6,55 @@ namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class Spi;
|
||||
class SpiNorFlash {
|
||||
public:
|
||||
explicit SpiNorFlash(Spi& spi);
|
||||
SpiNorFlash(const SpiNorFlash&) = delete;
|
||||
SpiNorFlash& operator=(const SpiNorFlash&) = delete;
|
||||
SpiNorFlash(SpiNorFlash&&) = delete;
|
||||
SpiNorFlash& operator=(SpiNorFlash&&) = delete;
|
||||
public:
|
||||
explicit SpiNorFlash(Spi& spi);
|
||||
SpiNorFlash(const SpiNorFlash&) = delete;
|
||||
SpiNorFlash& operator=(const SpiNorFlash&) = delete;
|
||||
SpiNorFlash(SpiNorFlash&&) = delete;
|
||||
SpiNorFlash& operator=(SpiNorFlash&&) = delete;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t manufacturer = 0;
|
||||
uint8_t type = 0;
|
||||
uint8_t density = 0;
|
||||
} Identification;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t manufacturer = 0;
|
||||
uint8_t type = 0;
|
||||
uint8_t density = 0;
|
||||
} Identification;
|
||||
|
||||
Identification ReadIdentificaion();
|
||||
uint8_t ReadStatusRegister();
|
||||
bool WriteInProgress();
|
||||
bool WriteEnabled();
|
||||
uint8_t ReadConfigurationRegister();
|
||||
void Read(uint32_t address, uint8_t* buffer, size_t size);
|
||||
void Write(uint32_t address, const uint8_t *buffer, size_t size);
|
||||
void WriteEnable();
|
||||
void SectorErase(uint32_t sectorAddress);
|
||||
uint8_t ReadSecurityRegister();
|
||||
bool ProgramFailed();
|
||||
bool EraseFailed();
|
||||
Identification ReadIdentificaion();
|
||||
uint8_t ReadStatusRegister();
|
||||
bool WriteInProgress();
|
||||
bool WriteEnabled();
|
||||
uint8_t ReadConfigurationRegister();
|
||||
void Read(uint32_t address, uint8_t* buffer, size_t size);
|
||||
void Write(uint32_t address, const uint8_t* buffer, size_t size);
|
||||
void WriteEnable();
|
||||
void SectorErase(uint32_t sectorAddress);
|
||||
uint8_t ReadSecurityRegister();
|
||||
bool ProgramFailed();
|
||||
bool EraseFailed();
|
||||
|
||||
void Init();
|
||||
void Uninit();
|
||||
|
||||
void Init();
|
||||
void Uninit();
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
|
||||
private:
|
||||
enum class Commands : uint8_t {
|
||||
PageProgram = 0x02,
|
||||
Read = 0x03,
|
||||
ReadStatusRegister = 0x05,
|
||||
WriteEnable = 0x06,
|
||||
ReadConfigurationRegister = 0x15,
|
||||
SectorErase = 0x20,
|
||||
ReadSecurityRegister = 0x2B,
|
||||
ReadIdentification = 0x9F,
|
||||
ReleaseFromDeepPowerDown = 0xAB,
|
||||
DeepPowerDown = 0xB9
|
||||
};
|
||||
static constexpr uint16_t pageSize = 256;
|
||||
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
private:
|
||||
enum class Commands : uint8_t {
|
||||
PageProgram = 0x02,
|
||||
Read = 0x03,
|
||||
ReadStatusRegister = 0x05,
|
||||
WriteEnable = 0x06,
|
||||
ReadConfigurationRegister = 0x15,
|
||||
SectorErase = 0x20,
|
||||
ReadSecurityRegister = 0x2B,
|
||||
ReadIdentification = 0x9F,
|
||||
ReleaseFromDeepPowerDown = 0xAB,
|
||||
DeepPowerDown = 0xB9
|
||||
};
|
||||
static constexpr uint16_t pageSize = 256;
|
||||
|
||||
Spi& spi;
|
||||
Identification device_id;
|
||||
Spi& spi;
|
||||
Identification device_id;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -6,11 +6,9 @@
|
||||
|
||||
using namespace Pinetime::Drivers;
|
||||
|
||||
St7789::St7789(Spi &spi, uint8_t pinDataCommand) : spi{spi}, pinDataCommand{pinDataCommand} {
|
||||
|
||||
St7789::St7789(Spi& spi, uint8_t pinDataCommand) : spi {spi}, pinDataCommand {pinDataCommand} {
|
||||
}
|
||||
|
||||
|
||||
void St7789::Init() {
|
||||
spi.Init();
|
||||
nrf_gpio_cfg_output(pinDataCommand);
|
||||
@@ -38,9 +36,8 @@ void St7789::WriteData(uint8_t data) {
|
||||
WriteSpi(&data, 1);
|
||||
}
|
||||
|
||||
|
||||
void St7789::WriteSpi(const uint8_t* data, size_t size) {
|
||||
spi.Write(data, size);
|
||||
spi.Write(data, size);
|
||||
}
|
||||
|
||||
void St7789::SoftwareReset() {
|
||||
@@ -105,7 +102,7 @@ void St7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||
WriteData(x1 & 0xff);
|
||||
|
||||
WriteCommand(static_cast<uint8_t>(Commands::RowAddressSet));
|
||||
WriteData(y0>>8);
|
||||
WriteData(y0 >> 8);
|
||||
WriteData(y0 & 0xff);
|
||||
WriteData(y1 >> 8);
|
||||
WriteData(y1 & 0xff);
|
||||
@@ -139,21 +136,20 @@ void St7789::VerticalScrollStartAddress(uint16_t line) {
|
||||
WriteData(line & 0x00ffu);
|
||||
}
|
||||
|
||||
|
||||
void St7789::Uninit() {
|
||||
|
||||
}
|
||||
|
||||
void St7789::DrawPixel(uint16_t x, uint16_t y, uint32_t color) {
|
||||
if((x < 0) ||(x >= Width) || (y < 0) || (y >= Height)) return;
|
||||
if ((x < 0) || (x >= Width) || (y < 0) || (y >= Height))
|
||||
return;
|
||||
|
||||
SetAddrWindow(x, y, x+1, y+1);
|
||||
SetAddrWindow(x, y, x + 1, y + 1);
|
||||
|
||||
nrf_gpio_pin_set(pinDataCommand);
|
||||
WriteSpi(reinterpret_cast<const uint8_t *>(&color), 2);
|
||||
WriteSpi(reinterpret_cast<const uint8_t*>(&color), 2);
|
||||
}
|
||||
|
||||
void St7789::DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *data, size_t size) {
|
||||
void St7789::DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t* data, size_t size) {
|
||||
SetAddrWindow(x, y, x + width - 1, y + height - 1);
|
||||
nrf_gpio_pin_set(pinDataCommand);
|
||||
WriteSpi(data, size);
|
||||
|
@@ -6,69 +6,68 @@ namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class Spi;
|
||||
class St7789 {
|
||||
public:
|
||||
explicit St7789(Spi& spi, uint8_t pinDataCommand);
|
||||
St7789(const St7789&) = delete;
|
||||
St7789& operator=(const St7789&) = delete;
|
||||
St7789(St7789&&) = delete;
|
||||
St7789& operator=(St7789&&) = delete;
|
||||
public:
|
||||
explicit St7789(Spi& spi, uint8_t pinDataCommand);
|
||||
St7789(const St7789&) = delete;
|
||||
St7789& operator=(const St7789&) = delete;
|
||||
St7789(St7789&&) = delete;
|
||||
St7789& operator=(St7789&&) = delete;
|
||||
|
||||
void Init();
|
||||
void Uninit();
|
||||
void DrawPixel(uint16_t x, uint16_t y, uint32_t color);
|
||||
void Init();
|
||||
void Uninit();
|
||||
void DrawPixel(uint16_t x, uint16_t y, uint32_t color);
|
||||
|
||||
void VerticalScrollDefinition(uint16_t topFixedLines, uint16_t scrollLines, uint16_t bottomFixedLines);
|
||||
void VerticalScrollStartAddress(uint16_t line);
|
||||
void VerticalScrollDefinition(uint16_t topFixedLines, uint16_t scrollLines, uint16_t bottomFixedLines);
|
||||
void VerticalScrollStartAddress(uint16_t line);
|
||||
|
||||
void DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *data, size_t size);
|
||||
void DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t* data, size_t size);
|
||||
|
||||
void DisplayOn();
|
||||
void DisplayOff();
|
||||
void DisplayOn();
|
||||
void DisplayOff();
|
||||
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
private:
|
||||
Spi& spi;
|
||||
uint8_t pinDataCommand;
|
||||
uint8_t verticalScrollingStartAddress = 0;
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
|
||||
void HardwareReset();
|
||||
void SoftwareReset();
|
||||
void SleepOut();
|
||||
void SleepIn();
|
||||
void ColMod();
|
||||
void MemoryDataAccessControl();
|
||||
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);
|
||||
private:
|
||||
Spi& spi;
|
||||
uint8_t pinDataCommand;
|
||||
uint8_t verticalScrollingStartAddress = 0;
|
||||
|
||||
enum class Commands : uint8_t {
|
||||
SoftwareReset = 0x01,
|
||||
SleepIn = 0x10,
|
||||
SleepOut = 0x11,
|
||||
NormalModeOn = 0x13,
|
||||
DisplayInversionOn = 0x21,
|
||||
DisplayOff = 0x28,
|
||||
DisplayOn = 0x29,
|
||||
ColumnAddressSet = 0x2a,
|
||||
RowAddressSet = 0x2b,
|
||||
WriteToRam = 0x2c,
|
||||
MemoryDataAccessControl = 0x36,
|
||||
VerticalScrollDefinition = 0x33,
|
||||
VerticalScrollStartAddress = 0x37,
|
||||
ColMod = 0x3a,
|
||||
};
|
||||
void WriteData(uint8_t data);
|
||||
void ColumnAddressSet();
|
||||
void HardwareReset();
|
||||
void SoftwareReset();
|
||||
void SleepOut();
|
||||
void SleepIn();
|
||||
void ColMod();
|
||||
void MemoryDataAccessControl();
|
||||
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);
|
||||
|
||||
static constexpr uint16_t Width = 240;
|
||||
static constexpr uint16_t Height = 320;
|
||||
void RowAddressSet();
|
||||
enum class Commands : uint8_t {
|
||||
SoftwareReset = 0x01,
|
||||
SleepIn = 0x10,
|
||||
SleepOut = 0x11,
|
||||
NormalModeOn = 0x13,
|
||||
DisplayInversionOn = 0x21,
|
||||
DisplayOff = 0x28,
|
||||
DisplayOn = 0x29,
|
||||
ColumnAddressSet = 0x2a,
|
||||
RowAddressSet = 0x2b,
|
||||
WriteToRam = 0x2c,
|
||||
MemoryDataAccessControl = 0x36,
|
||||
VerticalScrollDefinition = 0x33,
|
||||
VerticalScrollStartAddress = 0x37,
|
||||
ColMod = 0x3a,
|
||||
};
|
||||
void WriteData(uint8_t data);
|
||||
void ColumnAddressSet();
|
||||
|
||||
static constexpr uint16_t Width = 240;
|
||||
static constexpr uint16_t Height = 320;
|
||||
void RowAddressSet();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -8,33 +8,39 @@ using namespace Pinetime::Drivers;
|
||||
// TODO use shortcut to automatically send STOP when receive LastTX, for example
|
||||
// TODO use DMA/IRQ
|
||||
|
||||
TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module{module}, params{params} {
|
||||
TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module {module}, params {params} {
|
||||
mutex = xSemaphoreCreateBinary();
|
||||
}
|
||||
|
||||
void TwiMaster::Init() {
|
||||
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_S0D1 << GPIO_PIN_CNF_DRIVE_Pos)
|
||||
| ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_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_S0D1 << 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_S0D1 << 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_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
|
||||
((uint32_t) GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||
|
||||
switch(module) {
|
||||
case Modules::TWIM1: twiBaseAddress = NRF_TWIM1; break;
|
||||
switch (module) {
|
||||
case Modules::TWIM1:
|
||||
twiBaseAddress = NRF_TWIM1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
switch(static_cast<Frequencies>(params.frequency)) {
|
||||
case Frequencies::Khz100 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K100; break;
|
||||
case Frequencies::Khz250 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K250; break;
|
||||
case Frequencies::Khz400 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400; break;
|
||||
switch (static_cast<Frequencies>(params.frequency)) {
|
||||
case Frequencies::Khz100:
|
||||
twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K100;
|
||||
break;
|
||||
case Frequencies::Khz250:
|
||||
twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K250;
|
||||
break;
|
||||
case Frequencies::Khz400:
|
||||
twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400;
|
||||
break;
|
||||
}
|
||||
|
||||
twiBaseAddress->PSEL.SCL = params.pinScl;
|
||||
@@ -49,7 +55,6 @@ void TwiMaster::Init() {
|
||||
|
||||
twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos);
|
||||
|
||||
|
||||
/* // IRQ
|
||||
NVIC_ClearPendingIRQ(_IRQn);
|
||||
NVIC_SetPriority(_IRQn, 2);
|
||||
@@ -57,10 +62,9 @@ void TwiMaster::Init() {
|
||||
*/
|
||||
|
||||
xSemaphoreGive(mutex);
|
||||
|
||||
}
|
||||
|
||||
TwiMaster::ErrorCodes 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);
|
||||
auto ret = Write(deviceAddress, ®isterAddress, 1, false);
|
||||
ret = Read(deviceAddress, data, size, true);
|
||||
@@ -68,7 +72,7 @@ TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAdd
|
||||
return ret;
|
||||
}
|
||||
|
||||
TwiMaster::ErrorCodes 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);
|
||||
internalBuffer[0] = registerAddress;
|
||||
@@ -78,22 +82,23 @@ TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAd
|
||||
return ret;
|
||||
}
|
||||
|
||||
TwiMaster::ErrorCodes 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;
|
||||
twiBaseAddress->RXD.PTR = (uint32_t) buffer;
|
||||
twiBaseAddress->RXD.MAXCNT = size;
|
||||
|
||||
twiBaseAddress->TASKS_STARTRX = 1;
|
||||
|
||||
while(!twiBaseAddress->EVENTS_RXSTARTED && !twiBaseAddress->EVENTS_ERROR);
|
||||
while (!twiBaseAddress->EVENTS_RXSTARTED && !twiBaseAddress->EVENTS_ERROR)
|
||||
;
|
||||
twiBaseAddress->EVENTS_RXSTARTED = 0x0UL;
|
||||
|
||||
txStartedCycleCount = DWT->CYCCNT;
|
||||
uint32_t currentCycleCount;
|
||||
while(!twiBaseAddress->EVENTS_LASTRX && !twiBaseAddress->EVENTS_ERROR) {
|
||||
while (!twiBaseAddress->EVENTS_LASTRX && !twiBaseAddress->EVENTS_ERROR) {
|
||||
currentCycleCount = DWT->CYCCNT;
|
||||
if ((currentCycleCount-txStartedCycleCount) > HwFreezedDelay) {
|
||||
if ((currentCycleCount - txStartedCycleCount) > HwFreezedDelay) {
|
||||
FixHwFreezed();
|
||||
return ErrorCodes::TransactionFailed;
|
||||
}
|
||||
@@ -102,12 +107,13 @@ TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t *buffer, si
|
||||
|
||||
if (stop || twiBaseAddress->EVENTS_ERROR) {
|
||||
twiBaseAddress->TASKS_STOP = 0x1UL;
|
||||
while(!twiBaseAddress->EVENTS_STOPPED);
|
||||
while (!twiBaseAddress->EVENTS_STOPPED)
|
||||
;
|
||||
twiBaseAddress->EVENTS_STOPPED = 0x0UL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
twiBaseAddress->TASKS_SUSPEND = 0x1UL;
|
||||
while(!twiBaseAddress->EVENTS_SUSPENDED);
|
||||
while (!twiBaseAddress->EVENTS_SUSPENDED)
|
||||
;
|
||||
twiBaseAddress->EVENTS_SUSPENDED = 0x0UL;
|
||||
}
|
||||
|
||||
@@ -117,22 +123,23 @@ TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t *buffer, si
|
||||
return ErrorCodes::NoError;
|
||||
}
|
||||
|
||||
TwiMaster::ErrorCodes 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;
|
||||
twiBaseAddress->TXD.PTR = (uint32_t) data;
|
||||
twiBaseAddress->TXD.MAXCNT = size;
|
||||
|
||||
twiBaseAddress->TASKS_STARTTX = 1;
|
||||
|
||||
while(!twiBaseAddress->EVENTS_TXSTARTED && !twiBaseAddress->EVENTS_ERROR);
|
||||
while (!twiBaseAddress->EVENTS_TXSTARTED && !twiBaseAddress->EVENTS_ERROR)
|
||||
;
|
||||
twiBaseAddress->EVENTS_TXSTARTED = 0x0UL;
|
||||
|
||||
txStartedCycleCount = DWT->CYCCNT;
|
||||
uint32_t currentCycleCount;
|
||||
while(!twiBaseAddress->EVENTS_LASTTX && !twiBaseAddress->EVENTS_ERROR) {
|
||||
while (!twiBaseAddress->EVENTS_LASTTX && !twiBaseAddress->EVENTS_ERROR) {
|
||||
currentCycleCount = DWT->CYCCNT;
|
||||
if ((currentCycleCount-txStartedCycleCount) > HwFreezedDelay) {
|
||||
if ((currentCycleCount - txStartedCycleCount) > HwFreezedDelay) {
|
||||
FixHwFreezed();
|
||||
return ErrorCodes::TransactionFailed;
|
||||
}
|
||||
@@ -141,12 +148,13 @@ TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t *dat
|
||||
|
||||
if (stop || twiBaseAddress->EVENTS_ERROR) {
|
||||
twiBaseAddress->TASKS_STOP = 0x1UL;
|
||||
while(!twiBaseAddress->EVENTS_STOPPED);
|
||||
while (!twiBaseAddress->EVENTS_STOPPED)
|
||||
;
|
||||
twiBaseAddress->EVENTS_STOPPED = 0x0UL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
twiBaseAddress->TASKS_SUSPEND = 0x1UL;
|
||||
while(!twiBaseAddress->EVENTS_SUSPENDED);
|
||||
while (!twiBaseAddress->EVENTS_SUSPENDED)
|
||||
;
|
||||
twiBaseAddress->EVENTS_SUSPENDED = 0x0UL;
|
||||
}
|
||||
|
||||
@@ -160,7 +168,7 @@ TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t *dat
|
||||
}
|
||||
|
||||
void TwiMaster::Sleep() {
|
||||
while(twiBaseAddress->ENABLE != 0) {
|
||||
while (twiBaseAddress->ENABLE != 0) {
|
||||
twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos);
|
||||
}
|
||||
nrf_gpio_cfg_default(6);
|
||||
@@ -184,17 +192,15 @@ void TwiMaster::FixHwFreezed() {
|
||||
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.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);
|
||||
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;
|
||||
|
@@ -7,39 +7,38 @@
|
||||
namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class TwiMaster {
|
||||
public:
|
||||
enum class Modules { TWIM1 };
|
||||
enum class Frequencies {Khz100, Khz250, Khz400};
|
||||
enum class ErrorCodes {NoError, TransactionFailed};
|
||||
struct Parameters {
|
||||
uint32_t frequency;
|
||||
uint8_t pinSda;
|
||||
uint8_t pinScl;
|
||||
};
|
||||
public:
|
||||
enum class Modules { TWIM1 };
|
||||
enum class Frequencies { Khz100, Khz250, Khz400 };
|
||||
enum class ErrorCodes { NoError, TransactionFailed };
|
||||
struct Parameters {
|
||||
uint32_t frequency;
|
||||
uint8_t pinSda;
|
||||
uint8_t pinScl;
|
||||
};
|
||||
|
||||
TwiMaster(const Modules module, const Parameters& params);
|
||||
TwiMaster(const Modules module, const Parameters& params);
|
||||
|
||||
void Init();
|
||||
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 Init();
|
||||
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();
|
||||
void Sleep();
|
||||
void Wakeup();
|
||||
|
||||
private:
|
||||
|
||||
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;
|
||||
const Parameters params;
|
||||
static constexpr uint8_t maxDataSize{16};
|
||||
static constexpr uint8_t registerSize{1};
|
||||
uint8_t internalBuffer[maxDataSize + registerSize];
|
||||
uint32_t txStartedCycleCount = 0;
|
||||
static constexpr uint32_t HwFreezedDelay{161000};
|
||||
private:
|
||||
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;
|
||||
const Parameters params;
|
||||
static constexpr uint8_t maxDataSize {16};
|
||||
static constexpr uint8_t registerSize {1};
|
||||
uint8_t internalBuffer[maxDataSize + registerSize];
|
||||
uint32_t txStartedCycleCount = 0;
|
||||
static constexpr uint32_t HwFreezedDelay {161000};
|
||||
};
|
||||
}
|
||||
}
|
@@ -2,7 +2,6 @@
|
||||
#include <mdk/nrf.h>
|
||||
using namespace Pinetime::Drivers;
|
||||
|
||||
|
||||
void Watchdog::Setup(uint8_t timeoutSeconds) {
|
||||
NRF_WDT->CONFIG &= ~(WDT_CONFIG_SLEEP_Msk << WDT_CONFIG_SLEEP_Pos);
|
||||
NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Run << WDT_CONFIG_SLEEP_Pos);
|
||||
@@ -12,7 +11,7 @@ void Watchdog::Setup(uint8_t timeoutSeconds) {
|
||||
|
||||
/* timeout (s) = (CRV + 1) / 32768 */
|
||||
// JF : 7500 = 7.5s
|
||||
uint32_t crv = (((timeoutSeconds*1000u) << 15u) / 1000) - 1;
|
||||
uint32_t crv = (((timeoutSeconds * 1000u) << 15u) / 1000) - 1;
|
||||
NRF_WDT->CRV = crv;
|
||||
|
||||
/* Enable reload requests */
|
||||
@@ -33,28 +32,46 @@ Watchdog::ResetReasons Watchdog::ActualResetReason() const {
|
||||
uint32_t reason = NRF_POWER->RESETREAS;
|
||||
NRF_POWER->RESETREAS = 0xffffffff;
|
||||
|
||||
if(reason & 0x01u) return ResetReasons::ResetPin;
|
||||
if((reason >> 1u) & 0x01u) return ResetReasons::Watchdog;
|
||||
if((reason >> 2u) & 0x01u) return ResetReasons::SoftReset;
|
||||
if((reason >> 3u) & 0x01u) return ResetReasons::CpuLockup;
|
||||
if((reason >> 16u) & 0x01u) return ResetReasons::SystemOff;
|
||||
if((reason >> 17u) & 0x01u) return ResetReasons::LpComp;
|
||||
if((reason) & 0x01u) return ResetReasons::DebugInterface;
|
||||
if((reason >> 19u) & 0x01u) return ResetReasons::NFC;
|
||||
if (reason & 0x01u)
|
||||
return ResetReasons::ResetPin;
|
||||
if ((reason >> 1u) & 0x01u)
|
||||
return ResetReasons::Watchdog;
|
||||
if ((reason >> 2u) & 0x01u)
|
||||
return ResetReasons::SoftReset;
|
||||
if ((reason >> 3u) & 0x01u)
|
||||
return ResetReasons::CpuLockup;
|
||||
if ((reason >> 16u) & 0x01u)
|
||||
return ResetReasons::SystemOff;
|
||||
if ((reason >> 17u) & 0x01u)
|
||||
return ResetReasons::LpComp;
|
||||
if ((reason) &0x01u)
|
||||
return ResetReasons::DebugInterface;
|
||||
if ((reason >> 19u) & 0x01u)
|
||||
return ResetReasons::NFC;
|
||||
return ResetReasons::HardReset;
|
||||
}
|
||||
|
||||
const char *Watchdog::ResetReasonToString(Watchdog::ResetReasons reason) {
|
||||
switch(reason) {
|
||||
case ResetReasons::ResetPin: return "Reset pin";
|
||||
case ResetReasons::Watchdog: return "Watchdog";
|
||||
case ResetReasons::DebugInterface: return "Debug interface";
|
||||
case ResetReasons::LpComp: return "LPCOMP";
|
||||
case ResetReasons::SystemOff: return "System OFF";
|
||||
case ResetReasons::CpuLockup: return "CPU Lock-up";
|
||||
case ResetReasons::SoftReset: return "Soft reset";
|
||||
case ResetReasons::NFC: return "NFC";
|
||||
case ResetReasons::HardReset: return "Hard reset";
|
||||
default: return "Unknown";
|
||||
const char* Watchdog::ResetReasonToString(Watchdog::ResetReasons reason) {
|
||||
switch (reason) {
|
||||
case ResetReasons::ResetPin:
|
||||
return "Reset pin";
|
||||
case ResetReasons::Watchdog:
|
||||
return "Watchdog";
|
||||
case ResetReasons::DebugInterface:
|
||||
return "Debug interface";
|
||||
case ResetReasons::LpComp:
|
||||
return "LPCOMP";
|
||||
case ResetReasons::SystemOff:
|
||||
return "System OFF";
|
||||
case ResetReasons::CpuLockup:
|
||||
return "CPU Lock-up";
|
||||
case ResetReasons::SoftReset:
|
||||
return "Soft reset";
|
||||
case ResetReasons::NFC:
|
||||
return "NFC";
|
||||
case ResetReasons::HardReset:
|
||||
return "Hard reset";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
@@ -4,25 +4,31 @@
|
||||
namespace Pinetime {
|
||||
namespace Drivers {
|
||||
class Watchdog {
|
||||
public:
|
||||
enum class ResetReasons { ResetPin, Watchdog, SoftReset, CpuLockup, SystemOff, LpComp, DebugInterface, NFC, HardReset };
|
||||
void Setup(uint8_t timeoutSeconds);
|
||||
void Start();
|
||||
void Kick();
|
||||
ResetReasons ResetReason() const { return resetReason; }
|
||||
static const char* ResetReasonToString(ResetReasons reason);
|
||||
private:
|
||||
ResetReasons resetReason;
|
||||
ResetReasons ActualResetReason() const;
|
||||
public:
|
||||
enum class ResetReasons { ResetPin, Watchdog, SoftReset, CpuLockup, SystemOff, LpComp, DebugInterface, NFC, HardReset };
|
||||
void Setup(uint8_t timeoutSeconds);
|
||||
void Start();
|
||||
void Kick();
|
||||
ResetReasons ResetReason() const {
|
||||
return resetReason;
|
||||
}
|
||||
static const char* ResetReasonToString(ResetReasons reason);
|
||||
|
||||
private:
|
||||
ResetReasons resetReason;
|
||||
ResetReasons ActualResetReason() const;
|
||||
};
|
||||
|
||||
class WatchdogView {
|
||||
public:
|
||||
WatchdogView(const Watchdog& watchdog) : watchdog{watchdog} { }
|
||||
Watchdog::ResetReasons ResetReason() const { return watchdog.ResetReason();}
|
||||
public:
|
||||
WatchdogView(const Watchdog& watchdog) : watchdog {watchdog} {
|
||||
}
|
||||
Watchdog::ResetReasons ResetReason() const {
|
||||
return watchdog.ResetReason();
|
||||
}
|
||||
|
||||
private:
|
||||
const Watchdog& watchdog;
|
||||
private:
|
||||
const Watchdog& watchdog;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user