From 8106cdd481a025f62f7345f14c0a3ffdddfd2bd4 Mon Sep 17 00:00:00 2001
From: "Ettore L. Pane" <ettore.pane4@gmail.com>
Date: Sun, 22 Oct 2023 17:59:50 +0200
Subject: [PATCH] Commit buggato (test di creazione driver)

---
 .vscode/c_cpp_properties.json                 |   5 +-
 CMakeLists.txt                                |   5 +-
 cmake/boardcore.cmake                         |   6 +
 src/shared/drivers/ettore/SPIDriver.cpp       | 114 ++++++++++++++++++
 src/shared/drivers/ettore/SPIDriver.h         |  30 +++++
 src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp |  46 +++++++
 src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h   |  81 +++++++++++++
 src/tests/sensors/test-ettore.cpp             |  36 ++++++
 src/tests/sensors/test-lis3dsh.cpp            |   5 +-
 src/tests/test-serial.cpp                     |  10 +-
 10 files changed, 327 insertions(+), 11 deletions(-)
 create mode 100644 src/shared/drivers/ettore/SPIDriver.cpp
 create mode 100644 src/shared/drivers/ettore/SPIDriver.h
 create mode 100644 src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp
 create mode 100644 src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h
 create mode 100644 src/tests/sensors/test-ettore.cpp

diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 895903d93..54a6c9482 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -428,9 +428,10 @@
                 "${defaultIncludePaths}",
                 "${workspaceFolder}/libs/miosix-kernel/miosix/arch/cortexM7_stm32f7/common",
                 "${workspaceFolder}/libs/miosix-kernel/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery",
-                "${workspaceFolder}/libs/miosix-kernel/miosix/config/arch/cortexM7_stm32f7/stm32f769ni_discovery"
+                "${workspaceFolder}/libs/miosix-kernel/miosix/config/arch/cortexM7_stm32f7/stm32f769ni_discovery",
+                "${workspaceFolder}/src/shared/sensors/LIS3DSH"
             ]
         }
     ],
     "version": 4
-}
+}
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aaba63944..aeff2d1c8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,6 +33,9 @@ project(SkywardBoardcore)
 #                                 Entrypoints                                 #
 #-----------------------------------------------------------------------------#
 
+add_executable(test-ettore src/tests/sensors/test-ettore.cpp)
+sbs_target(test-ettore stm32f407vg_stm32f4discovery)
+
 add_executable(bmx160-calibration-v2 src/entrypoints/bmx160-calibration-entry.cpp)
 sbs_target(bmx160-calibration-v2 stm32f429zi_skyward_death_stack_x)
 
@@ -106,7 +109,7 @@ add_executable(test-sensormanager src/tests/test-sensormanager.cpp)
 sbs_target(test-sensormanager stm32f429zi_skyward_death_stack_x)
 
 add_executable(test-serial src/tests/test-serial.cpp)
-sbs_target(test-serial stm32f756zg_nucleo)
+sbs_target(test-serial stm32f407vg_stm32f4discovery)
 
 add_executable(test-taskscheduler src/tests/scheduler/test-taskscheduler.cpp)
 sbs_target(test-taskscheduler stm32f407vg_stm32f4discovery)
diff --git a/cmake/boardcore.cmake b/cmake/boardcore.cmake
index 49c749382..e04b56c93 100644
--- a/cmake/boardcore.cmake
+++ b/cmake/boardcore.cmake
@@ -27,6 +27,12 @@ foreach(OPT_BOARD ${BOARDS})
     set(BOARDCORE_LIBRARY boardcore-${OPT_BOARD})
     add_library(${BOARDCORE_LIBRARY} STATIC EXCLUDE_FROM_ALL
 
+        # Ettore
+        ${SBS_BASE}/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp
+        ${SBS_BASE}/src/shared/drivers/ettore/SPIDriver.cpp
+
+
+
         # Actuators
         ${SBS_BASE}/src/shared/actuators/HBridge/HBridge.cpp
         ${SBS_BASE}/src/shared/actuators/Servo/Servo.cpp
diff --git a/src/shared/drivers/ettore/SPIDriver.cpp b/src/shared/drivers/ettore/SPIDriver.cpp
new file mode 100644
index 000000000..b153ae5a2
--- /dev/null
+++ b/src/shared/drivers/ettore/SPIDriver.cpp
@@ -0,0 +1,114 @@
+#include "SPIDriver.h"
+#include <utils/Debug.h>
+
+
+namespace Boardcore {
+
+SpiDriver::SpiDriver(){
+    
+} 
+
+void SpiDriver::config()
+{
+    // CS has to be configured as output and put to high state. This because the
+    // chip select, by design, is active low: when the master wants to communicate
+    // with a slave, it has to pull the corresponding CS line to low
+    cs::mode(miosix::Mode::OUTPUT);
+    cs::high();
+
+    // SCK, MISO and MOSI GPIOs have to be configured in alternate mode. In this
+    // mode they are controlled by the internal SPI peripheral and not by the
+    // GPIO control registers
+    sck::mode(miosix::Mode::ALTERNATE);
+    miso::mode(miosix::Mode::ALTERNATE);
+    mosi::mode(miosix::Mode::ALTERNATE);
+
+    // STM32F4 chips have many peripherals connected to the same pins. The selection
+    // of which peripheral is connected to the GPIO pins is done through this
+    // function.
+    // To have a list of all the peripherals and their corresponding alternate
+    // function number, see device's datasheet in the section "Alternate function
+    // mapping".
+    // For the STM32F407VG the SPI1 is on alternate function number 5
+    sck::alternateFunction(5);
+    miso::alternateFunction(5);
+    mosi::alternateFunction(5);
+
+    TRACE("[SpiDriver] GPIOs configured \n");
+
+    {
+        // Disable interrupts
+        miosix::FastInterruptDisableLock dLock;
+        // Now enable the SPI peripheral by setting to 1 the corresponding bit into
+        // the clock gating register. This gives clock to peripheral's hardware
+        // allowing to read and write hardware. This operation must be done before
+        // accessing any of the peripheral's registers, otherwise reading and/or
+        // writing to them will have no effect.
+        RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
+        RCC_SYNC();
+    }
+
+    // Once clock has been enabled, configure the SPI peripheral writing to its
+    // registers.
+    // For detailed informations, see the reference manual for the STM32F407xx
+    // family at page 857 and following
+    SPI1->CR1 = SPI_CR1_SSM     // Software slave management enabled, CS line
+                                // is controlled by software and not by the peripheral
+
+              | SPI_CR1_SSI     // Internal slave select, see above
+
+              | SPI_CR1_MSTR    // Peripheral is an SPI master
+
+              | SPI_CR1_BR_2    // Division factor for SPI clock generation.
+                                // SPI1 is connected to APB2 bus, which is clocked
+                                // at 84MHz. Setting to 1 the third bit of division
+                                // factor we obtain an SCK frequency of 84MHz / 32 = 2.625MHz
+
+              | SPI_CR1_SPE;    // Finally enable the peripheral
+
+    TRACE("[SpiDriver] SPI1 configured \n");
+}
+
+uint8_t SpiDriver::sendRecv(uint8_t data)
+{
+    SPI1->DR = data;
+    waitBusy();
+    return SPI1->DR;
+}
+
+void SpiDriver::waitBusy()
+{
+    // Wait until the RX Not Empty flag in peripheral's status
+    // register (SPI1->SR) is set. This signals that the data transfer
+    // is completed and the data received from the slave device is
+    // into data register (SPI1->DR)
+    while((SPI1->SR & SPI_SR_RXNE) == 0)
+    {
+    }
+}
+
+void SpiDriver::write(uint8_t addr, uint8_t value)
+{
+    cs::low();
+
+    sendRecv(addr);
+    sendRecv(value);
+
+    cs::high();
+    miosix::delayUs(10); // wait 10 microseconds
+}
+
+uint8_t SpiDriver::read(uint8_t addr)
+{
+    cs::low();
+    sendRecv(0x80 | addr); // <--deeper
+    uint8_t data = sendRecv(0x00);
+
+    cs::high();
+    miosix::delayUs(10); // wait 10 microseconds
+    printf("returning\n");
+
+    return data;
+}
+
+} // namespace Boardcore
\ No newline at end of file
diff --git a/src/shared/drivers/ettore/SPIDriver.h b/src/shared/drivers/ettore/SPIDriver.h
new file mode 100644
index 000000000..6fbba0077
--- /dev/null
+++ b/src/shared/drivers/ettore/SPIDriver.h
@@ -0,0 +1,30 @@
+#include <miosix.h>
+
+namespace Boardcore {
+
+    typedef miosix::Gpio<GPIOA_BASE, 5> sck;
+    typedef miosix::Gpio<GPIOA_BASE, 6> miso;
+    typedef miosix::Gpio<GPIOA_BASE, 7> mosi;
+
+    typedef miosix::Gpio<GPIOE_BASE, 3> cs;
+
+    class SpiDriver
+    {
+    public:
+
+        SpiDriver();
+
+        void config();
+
+        uint8_t read(uint8_t addr);
+
+        void write(uint8_t addr, uint8_t value);
+
+    private:
+
+        uint8_t sendRecv(uint8_t data);
+
+        void waitBusy();
+    };
+
+} // namespace BoardCore
diff --git a/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp b/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp
new file mode 100644
index 000000000..d4b3f6411
--- /dev/null
+++ b/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp
@@ -0,0 +1,46 @@
+#include "LIS3DSH.h"
+
+namespace Boardcore {
+
+LIS3DSHettore::LIS3DSHettore(uint8_t odr, uint8_t bdu)
+    : odr(odr), bdu(bdu)
+{
+}
+
+bool LIS3DSHettore::checkWhoAmI()
+{
+    uint8_t who_am_i = spi_driver.read(WHO_AM_I_REG); // <-- we need to go deeper
+
+    if (who_am_i == WHO_AM_I_VALUE)
+    {
+
+        return true;
+    }
+    
+    return false;
+}
+
+bool LIS3DSHettore::init()
+{
+    if (!checkWhoAmI()) // wrong who_am_i value
+    {
+        printf("init not okay");
+        return false;
+    }
+    // set the output data rate and the BDU in CTRL_REG4
+    uint8_t ctrl_reg4_value = (odr << 4) | (bdu << 3);
+    spi_driver.write(CTRL_REG4, ctrl_reg4_value);
+    return true;  // correctly initialized
+}
+
+int8_t LIS3DSHettore::getTemperature()
+{
+    // the temperature is given as a 8-bits integer (in 2-complement)
+    // 1 LSB/deg - 8-bit resolution
+    // also, reading zero means 25 °C, so add the temperature reference
+    return spi_driver.read(OUT_T) + TEMPERATURE_REF;
+}
+
+}
+
+
diff --git a/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h b/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h
new file mode 100644
index 000000000..f13d5f688
--- /dev/null
+++ b/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h
@@ -0,0 +1,81 @@
+
+
+#pragma once
+
+#include "drivers/ettore/SPIDriver.h"
+
+namespace Boardcore
+{
+
+class LIS3DSHettore
+{
+
+public:
+    LIS3DSHettore(uint8_t odr, uint8_t bdu);
+
+    bool init();
+
+    bool checkWhoAmI();
+
+    int8_t getTemperature();
+
+        enum OutputDataRate : uint8_t
+    {
+        ODR_POWER_DOWN = 0,  // default value
+        ODR_3_125_HZ   = 1,
+        ODR_6_25_HZ    = 2,
+        ODR_12_5_HZ    = 3,
+        ODR_25_HZ      = 4,
+        ODR_50_HZ      = 5,
+        ODR_100_HZ     = 6,
+        ODR_400_HZ     = 7,
+        ODR_800_HZ     = 8,
+        ODR_1600_HZ    = 9
+    };
+
+    enum BlockDataUpdate : uint8_t
+    {
+        CONTINUOUS_UPDATE_MODE = 0,
+        UPDATE_AFTER_READ_MODE = 1  // values updated only when MSB and LSB are read
+    };
+
+    enum Registers : uint8_t
+    {
+        WHO_AM_I_REG = 0x0F,  
+        CTRL_REG4    = 0x20,  // control register to set ODR and BDU
+        OUT_T        = 0x0C   // temperature output register
+    };
+
+
+private:
+
+    SpiDriver spi_driver;
+    uint8_t odr;
+    uint8_t bdu;
+
+    const uint8_t WHO_AM_I_VALUE   = 63;
+    const uint8_t TEMPERATURE_REF = 25;
+};
+
+}  // namespace Boardcore
+
+enum OutputDataRate : uint8_t
+{
+    ODR_POWER_DOWN = 0,  // default value
+    ODR_3_125_HZ   = 1,
+    ODR_6_25_HZ    = 2,
+    ODR_12_5_HZ    = 3,
+    ODR_25_HZ      = 4,
+    ODR_50_HZ      = 5,
+    ODR_100_HZ     = 6,
+    ODR_400_HZ     = 7,
+    ODR_800_HZ     = 8,
+    ODR_1600_HZ    = 9
+};
+
+enum BlockDataUpdate : uint8_t
+{
+    CONTINUOUS_UPDATE_MODE = 0,
+    UPDATE_AFTER_READ_MODE = 1  // values updated only when MSB and LSB are read
+};
+
diff --git a/src/tests/sensors/test-ettore.cpp b/src/tests/sensors/test-ettore.cpp
new file mode 100644
index 000000000..c156c9b79
--- /dev/null
+++ b/src/tests/sensors/test-ettore.cpp
@@ -0,0 +1,36 @@
+#include <miosix.h>
+#include <utils/Debug.h>
+#include "sensors/LIS3DSH-ettore/LIS3DSH.h"
+
+using namespace miosix;
+using namespace Boardcore;
+
+int main()
+{
+    LIS3DSHettore driver(LIS3DSHettore::OutputDataRate::ODR_100_HZ,
+                           LIS3DSHettore::BlockDataUpdate::UPDATE_AFTER_READ_MODE);
+
+    
+    printf("Ciao\n");
+    if (driver.init())
+    {
+        while (true)
+        {
+            TRACE("Temp : %d °C \n", driver.getTemperature());
+            printf("Ciao\n");
+
+
+            Thread::sleep(2000);
+        }
+    } else {
+                while (true)
+        {
+            TRACE("error \n");
+            printf("Ciao\n");
+
+            Thread::sleep(2000);
+        }
+    }
+
+    return 0;
+}
diff --git a/src/tests/sensors/test-lis3dsh.cpp b/src/tests/sensors/test-lis3dsh.cpp
index 7588e9cca..4d64fedd0 100644
--- a/src/tests/sensors/test-lis3dsh.cpp
+++ b/src/tests/sensors/test-lis3dsh.cpp
@@ -38,6 +38,8 @@ GpioPin cs(GPIOE_BASE, 3);
 
 int main()
 {
+    Thread::sleep(500);
+
     spiSck.mode(miosix::Mode::ALTERNATE);
     spiSck.alternateFunction(5);
     spiMiso.mode(miosix::Mode::ALTERNATE);
@@ -53,6 +55,7 @@ int main()
 
     LIS3DSHData data;
 
+
     // sensor not initialized, should give the error
     sensor.sample();
     if (sensor.getLastError() != SensorErrors::NOT_INIT)
@@ -85,7 +88,7 @@ int main()
     Thread::sleep(500);
 
     // sample some data from the sensor
-    for (int i = 0; i < 5; i++)
+    for (int i = 0; i < 5000; i++)
     {
         // sensor intitialized, should return error if no new data exist
         sensor.sample();
diff --git a/src/tests/test-serial.cpp b/src/tests/test-serial.cpp
index b1d27f597..91c558163 100644
--- a/src/tests/test-serial.cpp
+++ b/src/tests/test-serial.cpp
@@ -26,13 +26,9 @@ using namespace miosix;
 
 int main()
 {
-    while (true)
-    {
-        ledOn();
-        printf("Serial is working!\n");
-        Thread::sleep(1000);
-        ledOff();
-        Thread::sleep(1000);
+    while (true) {
+        printf("Helo this is my test!\n");
+        Thread::sleep(500);
     }
 
     return 0;
-- 
GitLab