Add OLED display support

This commit is contained in:
MG-95 2021-10-29 21:53:09 +02:00
parent 6ec7d1b8bb
commit 548549f067
14 changed files with 322 additions and 68 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "src/BME68x-Sensor-API"] [submodule "src/BME68x-Sensor-API"]
path = src/BME68x-Sensor-API path = src/BME68x-Sensor-API
url = https://github.com/BoschSensortec/BME68x-Sensor-API.git url = https://github.com/BoschSensortec/BME68x-Sensor-API.git
[submodule "src/oled-driver"]
path = src/oled-driver
url = git@github.com:MG-5/oled-driver.git

View file

@ -11,15 +11,18 @@
"${workspaceFolder}/cubemx/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2", "${workspaceFolder}/cubemx/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2",
"${workspaceFolder}/cubemx/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3", "${workspaceFolder}/cubemx/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3",
"${workspaceFolder}/cubemx/Drivers/CMSIS/Device/ST/STM32L1xx/Include", "${workspaceFolder}/cubemx/Drivers/CMSIS/Device/ST/STM32L1xx/Include",
"${workspaceFolder}/cubemx/Drivers/CMSIS/Include" "${workspaceFolder}/cubemx/Drivers/CMSIS/Include",
"${workspaceFolder}/src",
"${workspaceFolder}/src/oled-driver/include",
"${workspaceFolder}/src/oled-driver"
], ],
"defines": [ "defines": [
"STM32L1", "DEBUG",
"STM32L152RC",
"STM32L152xC", "STM32L152xC",
"BME68X_DO_NOT_USE_FPU" "BME68X_DO_NOT_USE_FPU",
"FW_USE_RTOS"
], ],
"compilerPath": "arm-none-eabi-gcc", "compilerPath": "/usr/bin/arm-none-eabi-gcc",
"cStandard": "c11", "cStandard": "c11",
"cppStandard": "c++17" "cppStandard": "c++17"
} }

View file

@ -2,17 +2,24 @@ TARGET := voc-sensor
RTOS := freertos RTOS := freertos
DEVICE := stm32l152rc DEVICE := stm32l152rc
DEFS := BME68X_DO_NOT_USE_FPU DEFS += BME68X_DO_NOT_USE_FPU
DEFS += FW_USE_RTOS
INCDIRS := \ INCDIRS := \
src/BME68x-Sensor-API \
src/oled-driver/ \
src/oled-driver/include \
src \ src \
src/BME68x-Sensor-API
SOURCES := \ SOURCES := \
src/BME68x-Sensor-API/bme68x.c \
src/oled-driver/fonts/mono.cxx \
src/oled-driver/src/Display.cxx \
src/oled-driver/src/Image.cxx \
src/oled-driver/src/Renderer.cxx \
src/bmeSPI.cxx \ src/bmeSPI.cxx \
src/main.cxx \
src/handlers.cxx \ src/handlers.cxx \
src/BME68x-Sensor-API/bme68x.c src/main.cxx \
# Actual build engine # Actual build engine
include core/mk/include.mk include core/mk/include.mk

View file

@ -13,7 +13,13 @@ void *operator new(std::size_t size)
#if FW_USE_RTOS #if FW_USE_RTOS
return pvPortMalloc(size); return pvPortMalloc(size);
#else #else
return reinterpret_cast<void *>(0xffffffff); #ifdef DEBUG
__asm("bkpt");
#else
while (1)
{
}
#endif
#endif #endif
} }
@ -26,11 +32,15 @@ void operator delete(void *ptr)
{ {
#if FW_USE_RTOS #if FW_USE_RTOS
vPortFree(ptr); vPortFree(ptr);
#else
#ifdef DEBUG
__asm("bkpt");
#else #else
while (1) while (1)
{ {
} }
#endif #endif
#endif
} }
void operator delete(void *ptr, unsigned int) void operator delete(void *ptr, unsigned int)
@ -110,7 +120,7 @@ extern "C"
// some functions in cmath follow the compiler flag -fno-math-errno // some functions in cmath follow the compiler flag -fno-math-errno
// but not so for std::pow... // but not so for std::pow...
void __errno() { void __errno()
{
} }
} }

View file

@ -60,7 +60,7 @@
#define configTICK_RATE_HZ ((TickType_t)1000) #define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES ( 56 ) #define configMAX_PRIORITIES ( 56 )
#define configMINIMAL_STACK_SIZE ((uint16_t)128) #define configMINIMAL_STACK_SIZE ((uint16_t)128)
#define configTOTAL_HEAP_SIZE ((size_t)3072) #define configTOTAL_HEAP_SIZE ((size_t)6000)
#define configMAX_TASK_NAME_LEN ( 16 ) #define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1 #define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0
@ -68,8 +68,10 @@
#define configQUEUE_REGISTRY_SIZE 8 #define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 2 #define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_COUNTING_SEMAPHORES 1 #define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configRECORD_STACK_HIGH_ADDRESS 1
/* Co-routine definitions. */ /* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0 #define configUSE_CO_ROUTINES 0

View file

@ -58,8 +58,14 @@ void Error_Handler(void);
/* USER CODE END EFP */ /* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/
#define SPI_CS_Pin GPIO_PIN_12 #define VocSensorCS_Pin GPIO_PIN_0
#define SPI_CS_GPIO_Port GPIOB #define VocSensorCS_GPIO_Port GPIOA
#define DisplayDC_Pin GPIO_PIN_10
#define DisplayDC_GPIO_Port GPIOB
#define DisplayReset_Pin GPIO_PIN_11
#define DisplayReset_GPIO_Port GPIOB
#define DisplayCS_Pin GPIO_PIN_12
#define DisplayCS_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */ /* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */ /* USER CODE END Private defines */

View file

@ -75,6 +75,7 @@ void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/* Hook prototypes */ /* Hook prototypes */
void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName); void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName);
void vApplicationMallocFailedHook(void);
/* USER CODE BEGIN 4 */ /* USER CODE BEGIN 4 */
__weak void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName) __weak void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName)
@ -85,6 +86,22 @@ __weak void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTask
} }
/* USER CODE END 4 */ /* USER CODE END 4 */
/* USER CODE BEGIN 5 */
__weak void vApplicationMallocFailedHook(void)
{
/* vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
function that will get called if a call to pvPortMalloc() fails.
pvPortMalloc() is called internally by the kernel whenever a task, queue,
timer or semaphore is created. It is also called by various parts of the
demo application. If heap_1.c or heap_2.c are used, then the size of the
heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
to query the size of free heap space that remains (although it does not
provide information on how the remaining heap might be fragmented). */
}
/* USER CODE END 5 */
/** /**
* @brief FreeRTOS initialization * @brief FreeRTOS initialization
* @param None * @param None

View file

@ -53,7 +53,10 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */ /*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(VocSensorCS_GPIO_Port, VocSensorCS_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, DisplayDC_Pin|DisplayReset_Pin|DisplayCS_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PC13 PC14 PC15 PC0 /*Configure GPIO pins : PC13 PC14 PC15 PC0
PC1 PC2 PC3 PC4 PC1 PC2 PC3 PC4
@ -73,34 +76,41 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/*Configure GPIO pins : PA0 PA1 PA2 PA3 /*Configure GPIO pin : PtPin */
PA4 PA5 PA6 PA7 GPIO_InitStruct.Pin = VocSensorCS_Pin;
PA8 PA9 PA10 PA11 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
PA12 PA15 */ GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 HAL_GPIO_Init(VocSensorCS_GPIO_Port, &GPIO_InitStruct);
|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_15; /*Configure GPIO pins : PA1 PA2 PA3 PA4
PA5 PA6 PA7 PA8
PA9 PA10 PA11 PA12
PA15 */
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12
|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 PB1 PB2 PB10 /*Configure GPIO pins : PB0 PB1 PB2 PB3
PB11 PB3 PB4 PB5 PB4 PB5 PB6 PB7
PB6 PB7 PB8 PB9 */ PB8 PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_11|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7
|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; |GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */ /*Configure GPIO pins : PBPin PBPin PBPin */
GPIO_InitStruct.Pin = SPI_CS_Pin; GPIO_InitStruct.Pin = DisplayDC_Pin|DisplayReset_Pin|DisplayCS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SPI_CS_GPIO_Port, &GPIO_InitStruct); HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PD2 */ /*Configure GPIO pin : PD2 */
GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Pin = GPIO_PIN_2;

View file

@ -22,9 +22,12 @@ Dma.SPI2_TX.1.Priority=DMA_PRIORITY_LOW
Dma.SPI2_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority Dma.SPI2_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
FREERTOS.FootprintOK=true FREERTOS.FootprintOK=true
FREERTOS.HEAP_NUMBER=1 FREERTOS.HEAP_NUMBER=1
FREERTOS.IPParameters=Tasks01,configCHECK_FOR_STACK_OVERFLOW,FootprintOK,HEAP_NUMBER FREERTOS.IPParameters=Tasks01,configCHECK_FOR_STACK_OVERFLOW,FootprintOK,HEAP_NUMBER,configRECORD_STACK_HIGH_ADDRESS,configUSE_MALLOC_FAILED_HOOK,configTOTAL_HEAP_SIZE
FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;sensor,24,512,sensorTask,As external,NULL,Dynamic,NULL,NULL FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;sensor,24,512,sensorTask,As external,NULL,Dynamic,NULL,NULL
FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2 FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2
FREERTOS.configRECORD_STACK_HIGH_ADDRESS=1
FREERTOS.configTOTAL_HEAP_SIZE=6000
FREERTOS.configUSE_MALLOC_FAILED_HOOK=1
File.Version=6 File.Version=6
GPIO.groupedBy= GPIO.groupedBy=
KeepUserPlacement=false KeepUserPlacement=false
@ -38,15 +41,18 @@ Mcu.IP5=SYS
Mcu.IPNb=6 Mcu.IPNb=6
Mcu.Name=STM32L152RCTx Mcu.Name=STM32L152RCTx
Mcu.Package=LQFP64 Mcu.Package=LQFP64
Mcu.Pin0=PB12 Mcu.Pin0=PA0-WKUP1
Mcu.Pin1=PB13 Mcu.Pin1=PB10
Mcu.Pin2=PB14 Mcu.Pin10=VP_SYS_VS_tim2
Mcu.Pin3=PB15 Mcu.Pin2=PB11
Mcu.Pin4=PA13 Mcu.Pin3=PB12
Mcu.Pin5=PA14 Mcu.Pin4=PB13
Mcu.Pin6=VP_FREERTOS_VS_CMSIS_V2 Mcu.Pin5=PB14
Mcu.Pin7=VP_SYS_VS_tim2 Mcu.Pin6=PB15
Mcu.PinsNb=8 Mcu.Pin7=PA13
Mcu.Pin8=PA14
Mcu.Pin9=VP_FREERTOS_VS_CMSIS_V2
Mcu.PinsNb=11
Mcu.ThirdPartyNb=0 Mcu.ThirdPartyNb=0
Mcu.UserConstants= Mcu.UserConstants=
Mcu.UserName=STM32L152RCTx Mcu.UserName=STM32L152RCTx
@ -71,13 +77,21 @@ NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
NVIC.TimeBase=TIM2_IRQn NVIC.TimeBase=TIM2_IRQn
NVIC.TimeBaseIP=TIM2 NVIC.TimeBaseIP=TIM2
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA0-WKUP1.GPIOParameters=GPIO_Label
PA0-WKUP1.GPIO_Label=VocSensorCS
PA0-WKUP1.Signal=GPIO_Output
PA13.Mode=Serial_Wire PA13.Mode=Serial_Wire
PA13.Signal=SYS_JTMS-SWDIO PA13.Signal=SYS_JTMS-SWDIO
PA14.Mode=Serial_Wire PA14.Mode=Serial_Wire
PA14.Signal=SYS_JTCK-SWCLK PA14.Signal=SYS_JTCK-SWCLK
PB10.GPIOParameters=GPIO_Label
PB10.GPIO_Label=DisplayDC
PB10.Signal=GPIO_Output
PB11.GPIOParameters=GPIO_Label
PB11.GPIO_Label=DisplayReset
PB11.Signal=GPIO_Output
PB12.GPIOParameters=GPIO_Label PB12.GPIOParameters=GPIO_Label
PB12.GPIO_Label=SPI_CS PB12.GPIO_Label=DisplayCS
PB12.Locked=true
PB12.Signal=GPIO_Output PB12.Signal=GPIO_Output
PB13.Mode=Full_Duplex_Master PB13.Mode=Full_Duplex_Master
PB13.Signal=SPI2_SCK PB13.Signal=SPI2_SCK

88
src/SSD1306_SPI.hpp Normal file
View file

@ -0,0 +1,88 @@
#pragma once
#include "main.h"
#include "semphr.h"
#include "spi.h"
#include "oled-driver/SSD1306Interface.hpp"
constexpr size_t OledWidth = 128;
constexpr size_t OledPages = 4;
namespace
{
constexpr auto DisplaySpiPeripherie = &hspi2;
} // namespace
extern QueueHandle_t spiMutex;
extern void waitForSpiFinished();
//--------------------------------------------------------------------------------------------------
//! SPI interface to a SSD1305/6 display controller.
class SSD1306_SPI : public SSD1306Interface
{
public:
void writeCommand(uint8_t cmd) override
{
xSemaphoreTake(spiMutex, portMAX_DELAY);
setCommandPin();
setChipSelect(true);
HAL_SPI_Transmit_DMA(DisplaySpiPeripherie, &cmd, 1);
waitForSpiFinished();
setChipSelect(false);
xSemaphoreGive(spiMutex);
}
//--------------------------------------------------------------------------------------------------
void writeData(uint8_t data) override
{
xSemaphoreTake(spiMutex, portMAX_DELAY);
setDataPin();
setChipSelect(true);
HAL_SPI_Transmit_DMA(DisplaySpiPeripherie, &data, 1);
waitForSpiFinished();
setChipSelect(false);
xSemaphoreGive(spiMutex);
}
//--------------------------------------------------------------------------------------------------
void writeData(const uint8_t *data, unsigned int length) override
{
if (length > OledWidth * OledPages)
return;
xSemaphoreTake(spiMutex, portMAX_DELAY);
setDataPin();
setChipSelect(true);
HAL_SPI_Transmit_DMA(DisplaySpiPeripherie, const_cast<uint8_t *>(data), length);
waitForSpiFinished();
setChipSelect(false);
xSemaphoreGive(spiMutex);
}
//--------------------------------------------------------------------------------------------------
private:
void setDataPin()
{
HAL_GPIO_WritePin(DisplayDC_GPIO_Port, DisplayDC_Pin, GPIO_PIN_SET);
}
//--------------------------------------------------------------------------------------------------
void setCommandPin()
{
HAL_GPIO_WritePin(DisplayDC_GPIO_Port, DisplayDC_Pin, GPIO_PIN_RESET);
}
//--------------------------------------------------------------------------------------------------
void setChipSelect(bool state)
{
HAL_GPIO_WritePin(DisplayCS_GPIO_Port, DisplayCS_Pin,
state ? GPIO_PIN_RESET : GPIO_PIN_SET);
}
};

View file

@ -1,11 +1,21 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "gpio.h" #include "gpio.h"
#include "main.h" #include "main.h"
#include "semphr.h"
#include "spi.h" #include "spi.h"
#include "task.h" #include "task.h"
#include <cstring> #include <cstring>
#include "BME68x-Sensor-API/bme68x.h" #include "BME68x-Sensor-API/bme68x.h"
#include "oled-driver/Renderer.hpp"
extern QueueHandle_t spiMutex;
extern void waitForSpiFinished();
extern Renderer renderer;
constexpr auto MaximumChars = 22 * 4;
char buffer[MaximumChars];
constexpr auto SPI_DEVICE = &hspi2; constexpr auto SPI_DEVICE = &hspi2;
uint8_t txBuffer[512]; uint8_t txBuffer[512];
@ -29,17 +39,15 @@ uint16_t dur_prof[10] = {100, 100, 100, 100, 100, 100, 100, 100, 100, 100};
void setChipSelect(bool state) void setChipSelect(bool state)
{ {
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, state ? GPIO_PIN_RESET : GPIO_PIN_SET); HAL_GPIO_WritePin(VocSensorCS_GPIO_Port, VocSensorCS_Pin,
} state ? GPIO_PIN_RESET : GPIO_PIN_SET);
void waitForSpiFinished()
{
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
} }
// SPI read function map // SPI read function map
BME68X_INTF_RET_TYPE bme68x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *) BME68X_INTF_RET_TYPE bme68x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *)
{ {
xSemaphoreTake(spiMutex, portMAX_DELAY);
setChipSelect(true); setChipSelect(true);
HAL_SPI_Transmit_DMA(SPI_DEVICE, &reg_addr, 1); HAL_SPI_Transmit_DMA(SPI_DEVICE, &reg_addr, 1);
waitForSpiFinished(); waitForSpiFinished();
@ -47,6 +55,8 @@ BME68X_INTF_RET_TYPE bme68x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32
waitForSpiFinished(); waitForSpiFinished();
setChipSelect(false); setChipSelect(false);
xSemaphoreGive(spiMutex);
return 0; return 0;
} }
@ -60,11 +70,15 @@ BME68X_INTF_RET_TYPE bme68x_spi_write(uint8_t reg_addr, const uint8_t *reg_data,
txBuffer[0] = reg_addr; txBuffer[0] = reg_addr;
std::memcpy(&txBuffer[1], reg_data, len); std::memcpy(&txBuffer[1], reg_data, len);
xSemaphoreTake(spiMutex, portMAX_DELAY);
setChipSelect(true); setChipSelect(true);
HAL_SPI_Transmit_DMA(SPI_DEVICE, const_cast<uint8_t *>(txBuffer), len + 1); HAL_SPI_Transmit_DMA(SPI_DEVICE, const_cast<uint8_t *>(txBuffer), len + 1);
waitForSpiFinished(); waitForSpiFinished();
setChipSelect(false); setChipSelect(false);
xSemaphoreGive(spiMutex);
return 0; return 0;
} }
@ -153,10 +167,33 @@ void bmeRun()
/* Check if res == BME68X_OK, report or handle if otherwise */ /* Check if res == BME68X_OK, report or handle if otherwise */
for (uint8_t i = 0; i < n_fields; i++) for (uint8_t i = 0; i < n_fields; i++)
{ {
// printf("%u, %u, %d, %u, %u, %u, 0x%x, %d, %d\n", sampleCount, renderer.clearAll();
// time_ms,(bmeData[i].temperature / 100), bmeData[i].pressure, (bmeData[i].humidity /
// 1000),bmeData[i].gas_resistance, snprintf(buffer, MaximumChars,
// bmeData[i].status,data[i].gas_index,data[i].meas_index); "%d°C, %luhPa, %lu%%\n%lukOhm, status: 0x%x\ngas_index: %d\nmeas_index: %d",
bmeData[i].temperature / 100, //
bmeData[i].pressure / 100, //
bmeData[i].humidity / 1000, //
bmeData[i].gas_resistance / 1000, //
bmeData[i].status, //
bmeData[i].gas_index, //
bmeData[i].meas_index);
renderer.print({0, 0}, buffer);
renderer.render();
/*
snprintf(buffer, MaximumChars, "sampleCount: %u\n, time_ms: %u\n \
temperature; %d°C\n \
pressure: %u\n \
humidity: %u\n \
gas_resistance: %u\n \
// status: 0x%x\n \
//gas_index: %d\n \
meas_index: %d\n",
sampleCount, time_ms, (bmeData[i].temperature / 100), bmeData[i].pressure,
(bmeData[i].humidity / 1000), bmeData[i].gas_resistance, bmeData[i].status,
bmeData[i].gas_index, bmeData[i].meas_index);
*/
} }
} }

View file

@ -37,11 +37,15 @@ extern "C" void prvGetRegistersFromStack(uint32_t *pulFaultStackAddress)
(void)pc; (void)pc;
(void)psr; (void)psr;
/* When the following line is hit, the variables contain the register values. */ /* When the following line is hit, the variables contain the register values. */
// HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); // HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET);
#ifdef DEBUG
__asm("bkpt");
#else
while (1) while (1)
{ {
} }
#endif
} }
extern "C" void hard_fault_handler(void) extern "C" void hard_fault_handler(void)
@ -67,10 +71,13 @@ extern "C" void hard_fault_handler(void)
extern "C" void vApplicationMallocFailedHook(void) extern "C" void vApplicationMallocFailedHook(void)
{ {
// HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); #ifdef DEBUG
__asm("bkpt");
#else
while (1) while (1)
{ {
} }
#endif
} }
extern "C" void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName) extern "C" void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName)
@ -78,8 +85,11 @@ extern "C" void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCH
(void)pxTask; (void)pxTask;
(void)pcTaskName; (void)pcTaskName;
// HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); #ifdef DEBUG
__asm("bkpt");
#else
while (1) while (1)
{ {
} }
#endif
} }

View file

@ -1,33 +1,79 @@
#include "main.h" #include "main.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "semphr.h"
#include "task.h" #include "task.h"
#include "SSD1306_SPI.hpp"
#include "oled-driver/Display.hpp"
#include "oled-driver/Renderer.hpp"
extern TaskHandle_t sensorHandle; extern TaskHandle_t sensorHandle;
extern void bmeRun(); extern void bmeRun();
// oled display
SSD1306_SPI ssdSpiInterface;
Display display(ssdSpiInterface);
Renderer renderer(128, 4, display);
QueueHandle_t spiMutex = xSemaphoreCreateMutex();
QueueHandle_t spiBinary = xSemaphoreCreateBinary();
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void notifySensorTask() void initDisplay()
{
HAL_GPIO_WritePin(DisplayReset_GPIO_Port, DisplayReset_Pin, GPIO_PIN_RESET);
vTaskDelay(pdMS_TO_TICKS(1));
HAL_GPIO_WritePin(DisplayReset_GPIO_Port, DisplayReset_Pin, GPIO_PIN_SET);
vTaskDelay(pdMS_TO_TICKS(1));
display.setDisplayState(Display::DisplayState::Off);
display.setMultiplexRatio(OledPages * 8 - 1);
display.setComPinConfig(false, false);
display.setContrastControl(0xFF);
display.setDisplayClockDivide(0, 0x8);
display.setSegmentRemap(true);
display.setComOutputMode(Display::ComMode::Remap);
display.setPrechargingPeriod(1, 0xF);
display.setChargePump(true);
display.setMemoryAddressingMode(Display::AddressingMode::Horizontal);
display.setPageAddress(0, OledPages - 1); // pages from 0 to 3
display.setColumnAddress(0, OledWidth - 1); // columns from 0 to 127
display.setDisplayState(Display::DisplayState::On);
}
//--------------------------------------------------------------------------------------------------
void notifySpiIsFinished()
{ {
auto higherPriorityTaskWoken = pdFALSE; auto higherPriorityTaskWoken = pdFALSE;
vTaskNotifyGiveFromISR(sensorHandle, &higherPriorityTaskWoken); xSemaphoreGiveFromISR(spiBinary, &higherPriorityTaskWoken);
portYIELD_FROM_ISR(higherPriorityTaskWoken); portYIELD_FROM_ISR(higherPriorityTaskWoken);
} }
//--------------------------------------------------------------------------------------------------
void waitForSpiFinished()
{
xSemaphoreTake(spiBinary, portMAX_DELAY);
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *) extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *)
{ {
notifySensorTask(); notifySpiIsFinished();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *) extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *)
{ {
notifySensorTask(); notifySpiIsFinished();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
extern "C" void sensorTask(void *) extern "C" void sensorTask(void *)
{ {
initDisplay();
bmeRun(); bmeRun();
while (1) while (1)
{ {

1
src/oled-driver Submodule

@ -0,0 +1 @@
Subproject commit a224095e81a4728faa1311f0d717eb54959c6430