From c095c1087dd2a40d6d762a48eb0c3e72db2f0b0d Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Mon, 8 May 2023 01:32:20 +0300 Subject: [PATCH] forget to add files --- F3:F303/NitrogenFlooding/BMP280.c | 364 +++++++++++++++++++++++++++++ F3:F303/NitrogenFlooding/BMP280.h | 97 ++++++++ F3:F303/NitrogenFlooding/ili9341.c | 61 +++++ F3:F303/NitrogenFlooding/ili9341.h | 85 +++++++ F3:F303/NitrogenFlooding/spi.c | 114 +++++++++ F3:F303/NitrogenFlooding/spi.h | 35 +++ 6 files changed, 756 insertions(+) create mode 100644 F3:F303/NitrogenFlooding/BMP280.c create mode 100644 F3:F303/NitrogenFlooding/BMP280.h create mode 100644 F3:F303/NitrogenFlooding/ili9341.c create mode 100644 F3:F303/NitrogenFlooding/ili9341.h create mode 100644 F3:F303/NitrogenFlooding/spi.c create mode 100644 F3:F303/NitrogenFlooding/spi.h diff --git a/F3:F303/NitrogenFlooding/BMP280.c b/F3:F303/NitrogenFlooding/BMP280.c new file mode 100644 index 0000000..4770a2b --- /dev/null +++ b/F3:F303/NitrogenFlooding/BMP280.c @@ -0,0 +1,364 @@ +/** + * Ciastkolog.pl (https://github.com/ciastkolog) + * +*/ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 sheinz (https://github.com/sheinz) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "i2c.h" +#include "BMP280.h" + +#include + +#ifdef EBUG +#include "strfunc.h" +#include "usb.h" +#endif + +#define BMP280_I2C_ADDRESS_MASK (0x76) +#define BMP280_I2C_ADDRESS_0 (0x76) +#define BMP280_I2C_ADDRESS_1 (0x77) +/** + * BMP280 registers + */ +#define BMP280_REG_HUM_LSB 0xFE +#define BMP280_REG_HUM_MSB 0xFD +#define BMP280_REG_HUM (BMP280_REG_HUM_MSB) +#define BMP280_REG_TEMP_XLSB 0xFC /* bits: 7-4 */ +#define BMP280_REG_TEMP_LSB 0xFB +#define BMP280_REG_TEMP_MSB 0xFA +#define BMP280_REG_TEMP (BMP280_REG_TEMP_MSB) +#define BMP280_REG_PRESS_XLSB 0xF9 /* bits: 7-4 */ +#define BMP280_REG_PRESS_LSB 0xF8 +#define BMP280_REG_PRESS_MSB 0xF7 +#define BMP280_REG_PRESSURE (BMP280_REG_PRESS_MSB) +#define BMP280_REG_ALLDATA (BMP280_REG_PRESS_MSB) // all data: P, T & H +#define BMP280_REG_CONFIG 0xF5 /* bits: 7-5 t_sb; 4-2 filter; 0 spi3w_en */ +#define BMP280_REG_CTRL 0xF4 /* bits: 7-5 osrs_t; 4-2 osrs_p; 1-0 mode */ +#define BMP280_REG_STATUS 0xF3 /* bits: 3 measuring; 0 im_update */ +#define BMP280_REG_CTRL_HUM 0xF2 /* bits: 2-0 osrs_h; */ +#define BMP280_REG_RESET 0xE0 +#define BMP280_RESET_VALUE 0xB6 +#define BMP280_REG_ID 0xD0 + +#define BMP280_REG_CALIBA 0x88 +#define BMP280_CALIBA_SIZE (26) // 26 bytes of calibration registers sequence from 0x88 to 0xa1 +#define BMP280_CALIBB_SIZE (7) // 7 bytes of calibration registers sequence from 0xe1 to 0xe7 +#define BMP280_REG_CALIBB 0xE1 + +#define BMP280_MODE_FORSED (1) // force single measurement +#define BMP280_MODE_NORMAL (3) // run continuosly +#define BMP280_STATUS_MSRNG (1<<3) // measuring in process + +static uint8_t curaddress = BMP280_I2C_ADDRESS_0<<1; + +static struct { + // temperature + uint16_t dig_T1; // 0x88 (LSB), 0x98 (MSB) + int16_t dig_T2; // ... + int16_t dig_T3; + // pressure + uint16_t dig_P1; + int16_t dig_P2; + int16_t dig_P3; + int16_t dig_P4; + int16_t dig_P5; + int16_t dig_P6; + int16_t dig_P7; + int16_t dig_P8; + int16_t dig_P9; // 0x9e, 0x9f + // humidity (partially calculated from EEE struct) + uint8_t unused; // 0xA0 + uint8_t dig_H1; // 0xA1 + int16_t dig_H2; // -------------------- + uint8_t dig_H3; // only from EEE + uint16_t dig_H4; + uint16_t dig_H5; + int8_t dig_H6; + // data is ready + uint8_t rdy; +} __attribute__ ((packed)) CaliData = {0}; + +//T: 28222 26310 50 +//P: 37780 -10748 3024 7965 -43 -7 9900 -10230 4285 +//H: 75 25601 0 334 50 30 + +// data for humidity calibration of BME280 +static uint8_t EEE[BMP280_CALIBB_SIZE] = {0}; + +static struct{ + BMP280_Filter filter; // filtering + BMP280_Oversampling p_os; // oversampling for pressure + BMP280_Oversampling t_os; // -//- temperature + BMP280_Oversampling h_os; // -//- humidity + uint8_t ID; // identificator + uint8_t regctl; // control register base value [(params.t_os << 5) | (params.p_os << 2)] +} params = { + .filter = BMP280_FILTER_OFF, + .p_os = BMP280_OVERS16, + .t_os = BMP280_OVERS16, + .h_os = BMP280_OVERS16, + .ID = 0 +}; + +static BMP280_status bmpstatus = BMP280_NOTINIT; + +BMP280_status BMP280_get_status(){ + return bmpstatus; +} + +// address: 0 or 1 +void BMP280_setup(uint8_t address){ + curaddress = (BMP280_I2C_ADDRESS_MASK | (address & 1))<<1; + bmpstatus = BMP280_NOTINIT; + BMP280_init(); +} + +// setters for `params` +void BMP280_setfilter(BMP280_Filter f){ + params.filter = f; +} +BMP280_Filter BMP280_getfilter(){ + return params.filter; +} +void BMP280_setOSt(BMP280_Oversampling os){ + params.t_os = os; +} +void BMP280_setOSp(BMP280_Oversampling os){ + params.p_os = os; +} +void BMP280_setOSh(BMP280_Oversampling os){ + params.h_os = os; +} +// get compensation data, return 1 if OK +static int readcompdata(){ + if(!read_i2c_reg(curaddress, BMP280_REG_CALIBA, (uint8_t*)&CaliData, BMP280_CALIBA_SIZE)) return 0; + CaliData.rdy = 1; + if(params.ID == BME280_CHIP_ID){ + if(read_i2c_reg(curaddress, BMP280_REG_CALIBB, EEE, BMP280_CALIBB_SIZE)){ + CaliData.dig_H2 = (EEE[1] << 8) | EEE[0]; + CaliData.dig_H3 = EEE[2]; + CaliData.dig_H4 = (EEE[3] << 4) | (EEE[4] & 0x0f); + CaliData.dig_H5 = (EEE[5] << 4) | (EEE[4] >> 4); + CaliData.dig_H6 = EEE[6]; + } + } + return 1; +} + +static int read_reg(uint8_t reg, uint8_t *val){ + if(!read_i2c_reg(curaddress, reg, val, 1)) return 0; + return 1; +} +static int write_reg(uint8_t reg, uint8_t val){ + uint8_t d[2]; + d[0] = reg; d[1] = val; + if(!write_i2c(curaddress, d, 2)) return 0; + return 1; +} + +// read compensation data & write registers +int BMP280_init(){ + DBG("INI:\n"); + if(!read_reg(BMP280_REG_ID, ¶ms.ID)){ + DBG("Can't get ID\n"); + return 0; + } + if(params.ID != BMP280_CHIP_ID && params.ID != BME280_CHIP_ID){ + DBG("Not BMP/BME\n"); + return 0; + } + if(!write_reg(BMP280_REG_RESET, BMP280_RESET_VALUE)){ + DBG("Can't reset\n"); + return 0; + } + uint8_t reg = 1; + while(reg & 1){ + if(!read_reg(BMP280_REG_STATUS, ®)){ + DBG("can't get status\n"); + return 0; + } + } + if(!readcompdata()){ + DBG("Can't read calibration data\n"); + return 0; + } + // write filter configuration + reg = params.filter << 2; + if(!write_reg(BMP280_REG_CONFIG, reg)){DBG("Can't save filter settings\n");} + reg = (params.t_os << 5) | (params.p_os << 2); // oversampling for P/T, sleep mode + if(!write_reg(BMP280_REG_CTRL, reg)){ + DBG("Can't write settings for P/T\n"); + return 0; + } + params.regctl = reg; + if(params.ID == BME280_CHIP_ID){ // write CTRL_HUM only AFTER CTRL! + reg = params.h_os; + if(!write_reg(BMP280_REG_CTRL_HUM, reg)){ + DBG("Can't write settings for H\n"); + return 0; + } + } + bmpstatus = BMP280_RELAX; + return 1; +} + +// @return 1 if OK, *devid -> BMP/BME +int BMP280_read_ID(uint8_t *devid){ + if(params.ID != BMP280_CHIP_ID && params.ID != BME280_CHIP_ID) return 0; + *devid = params.ID; + return 1; +} + +// start measurement, @return 1 if all OK +int BMP280_start(){ + if(!CaliData.rdy || bmpstatus == BMP280_BUSY){ +#ifdef EBUG + USB_sendstr("rdy="); USB_sendstr(u2str(CaliData.rdy)); + USB_sendstr("\nbmpstatus="); USB_sendstr(u2str(bmpstatus)); + newline(); +#endif + return 0; + } + uint8_t reg = params.regctl | BMP280_MODE_FORSED; + if(!write_reg(BMP280_REG_CTRL, reg)){ + DBG("Can't write CTRL reg\n"); + return 0; + } + bmpstatus = BMP280_BUSY; + return 1; +} + +void BMP280_process(){ + if(bmpstatus == BMP280_NOTINIT){ + BMP280_init(); return; + } + if(bmpstatus != BMP280_BUSY) return; + // BUSY state: poll data ready + uint8_t reg; + if(!read_reg(BMP280_REG_STATUS, ®)) return; + if(reg & BMP280_STATUS_MSRNG) return; // still busy + bmpstatus = BMP280_RDY; // data ready +} + +// return T*100 degC +static inline int32_t compTemp(int32_t adc_temp, int32_t *t_fine){ + int32_t var1, var2; + var1 = ((((adc_temp >> 3) - ((int32_t) CaliData.dig_T1 << 1))) + * (int32_t) CaliData.dig_T2) >> 11; + var2 = (((((adc_temp >> 4) - (int32_t) CaliData.dig_T1) + * ((adc_temp >> 4) - (int32_t) CaliData.dig_T1)) >> 12) + * (int32_t) CaliData.dig_T3) >> 14; + *t_fine = var1 + var2; + return (*t_fine * 5 + 128) >> 8; +} + +// return p*256 hPa +static inline uint32_t compPres(int32_t adc_press, int32_t fine_temp) { + int64_t var1, var2, p; + var1 = (int64_t) fine_temp - 128000; + var2 = var1 * var1 * (int64_t) CaliData.dig_P6; + var2 = var2 + ((var1 * (int64_t) CaliData.dig_P5) << 17); + var2 = var2 + (((int64_t) CaliData.dig_P4) << 35); + var1 = ((var1 * var1 * (int64_t) CaliData.dig_P3) >> 8) + + ((var1 * (int64_t) CaliData.dig_P2) << 12); + var1 = (((int64_t) 1 << 47) + var1) * ((int64_t) CaliData.dig_P1) >> 33; + if (var1 == 0){ + return 0; // avoid exception caused by division by zero + } + p = 1048576 - adc_press; + p = (((p << 31) - var2) * 3125) / var1; + var1 = ((int64_t) CaliData.dig_P9 * (p >> 13) * (p >> 13)) >> 25; + var2 = ((int64_t) CaliData.dig_P8 * p) >> 19; + p = ((p + var1 + var2) >> 8) + ((int64_t) CaliData.dig_P7 << 4); + return p; +} + +// return H*1024 % +static inline uint32_t compHum(int32_t adc_hum, int32_t fine_temp){ + int32_t v_x1_u32r; + v_x1_u32r = fine_temp - (int32_t) 76800; + v_x1_u32r = ((((adc_hum << 14) - (((int32_t)CaliData.dig_H4) << 20) + - (((int32_t)CaliData.dig_H5) * v_x1_u32r)) + (int32_t)16384) >> 15) + * (((((((v_x1_u32r * ((int32_t)CaliData.dig_H6)) >> 10) + * (((v_x1_u32r * ((int32_t)CaliData.dig_H3)) >> 11) + + (int32_t)32768)) >> 10) + (int32_t)2097152) + * ((int32_t)CaliData.dig_H2) + 8192) >> 14); + v_x1_u32r = v_x1_u32r + - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) + * ((int32_t)CaliData.dig_H1)) >> 4); + v_x1_u32r = v_x1_u32r < 0 ? 0 : v_x1_u32r; + v_x1_u32r = v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r; + return v_x1_u32r >> 12; +} + + +// read data & convert it +int BMP280_getdata(float *T, float *P, float *H){ + if(bmpstatus != BMP280_RDY) return 0; + bmpstatus = BMP280_RELAX; + uint8_t data[8]; + uint8_t datasz = 8; // amount of bytes to read + if(params.ID != BME280_CHIP_ID){ + DBG("Not BME!\n"); + if(H) *H = 0; + H = NULL; + datasz = 6; + } + if(!read_i2c_reg(curaddress, BMP280_REG_ALLDATA, data, datasz)) return 0; + int32_t p = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4); + int32_t t = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4); + int32_t t_fine; + int32_t Temp = compTemp(t, &t_fine); + if(T) *T = ((float)Temp)/100.f; + if(P) *P = ((float)compPres(p, t_fine)) / 256.f; + if(H){ + int32_t h = (data[6] << 8) | data[7]; + *H = ((float)compHum(h, t_fine))/1024.; + } + return 1; +} + +// dewpoint calculation (T in degrC, H in percents) +float Tdew(float T, float H){ + float gamma = 17.27f * T / (237.7f + T) + log(H/100.f); + return (237.7f * gamma)/(17.27 - gamma); +} diff --git a/F3:F303/NitrogenFlooding/BMP280.h b/F3:F303/NitrogenFlooding/BMP280.h new file mode 100644 index 0000000..d04b133 --- /dev/null +++ b/F3:F303/NitrogenFlooding/BMP280.h @@ -0,0 +1,97 @@ +/** + * Ciastkolog.pl (https://github.com/ciastkolog) + * +*/ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 sheinz (https://github.com/sheinz) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#ifndef BMP280_H__ +#define BMP280_H__ + +#include + +#define BMP280_CHIP_ID 0x58 +#define BME280_CHIP_ID 0x60 + +typedef enum{ // K for filtering: next = [prev*(k-1) + data_ADC]/k + BMP280_FILTER_OFF = 0, // k=1, no filtering + BMP280_FILTER_2 = 1, // k=2, 2 samples to reach >75% of data_ADC + BMP280_FILTER_4 = 2, // k=4, 5 samples + BMP280_FILTER_8 = 3, // k=8, 11 samples + BMP280_FILTER_16 = 4, // k=16, 22 samples + BMP280_FILTERMAX +} BMP280_Filter; + +typedef enum{ // Number of oversampling + BMP280_NOMEASUR = 0, + BMP280_OVERS1 = 1, + BMP280_OVERS2 = 2, + BMP280_OVERS4 = 3, + BMP280_OVERS8 = 4, + BMP280_OVERS16 = 5, + BMP280_OVERSMAX +} BMP280_Oversampling; + +typedef enum{ + BMP280_NOTINIT, // wasn't inited + BMP280_BUSY, // measurement in progress + BMP280_ERR, // error in I2C + BMP280_RELAX, // relaxed state + BMP280_RDY, // data ready - can get it +} BMP280_status; + + +void BMP280_setup(uint8_t address); +int BMP280_init(); +void BMP280_setfilter(BMP280_Filter f); +BMP280_Filter BMP280_getfilter(); +void BMP280_setOSt(BMP280_Oversampling os); +void BMP280_setOSp(BMP280_Oversampling os); +void BMP280_setOSh(BMP280_Oversampling os); +int BMP280_read_ID(uint8_t *devid); +BMP280_status BMP280_get_status(); +int BMP280_start(); +void BMP280_process(); +int BMP280_getdata(float *T, float *P, float *H); +float Tdew(float T, float H); + +#endif // BMP280_H__ diff --git a/F3:F303/NitrogenFlooding/ili9341.c b/F3:F303/NitrogenFlooding/ili9341.c new file mode 100644 index 0000000..52270ba --- /dev/null +++ b/F3:F303/NitrogenFlooding/ili9341.c @@ -0,0 +1,61 @@ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hardware.h" +#include "ili9341.h" +#include "spi.h" +#ifdef EBUG +#include "strfunc.h" +#endif +#include "usb.h" + +/** + * @brief il9341_readreg - read data from register + * @param reg - register + * @param data (i) - data + * @param N - length of data + * @return 0 if failed + */ +int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N){ + SCRN_Command(); + if(!spi_write(®, 1)) return 0; + if(!spi_waitbsy()) return 0; + SCRN_Data(); + if(!spi_read(data, N)) return 0; + if(!spi_waitbsy()) return 0; + SCRN_Command(); + return 1; +} + +/** + * @brief il9341_writereg - write data to register + * @param reg - register + * @param data (o) - data + * @param N - length of data + * @return 0 if failed + */ +int ili9341_writereg(uint8_t _U_ reg, const uint8_t _U_ *data, uint32_t _U_ N){ + SCRN_Command(); + if(!spi_write(®, 1)) return 0; + if(!spi_waitbsy()) return 0; + SCRN_Data(); + if(!spi_write(data, N)) return 0; + if(!spi_waitbsy()) return 0; + SCRN_Command(); + return 1; +} diff --git a/F3:F303/NitrogenFlooding/ili9341.h b/F3:F303/NitrogenFlooding/ili9341.h new file mode 100644 index 0000000..fb00fcb --- /dev/null +++ b/F3:F303/NitrogenFlooding/ili9341.h @@ -0,0 +1,85 @@ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +// in 4-wire SPI mode there's 16-bit color data: (MSB) 5R-6G-5B (LSB) +#define RGB(r,g,b) (((r&0x1f)<<11)|((g&0x3f)<<5)|((b&0x1F))) + +/***** Registers *****/ +// No-op register +#define ILI9341_NOP 0x00 +// Software reset register +#define ILI9341_SWRESET 0x01 +// Read display identification information +#define ILI9341_RDDID 0x04 +// Read Display Status +#define ILI9341_RDDST 0x09 +// Enter Sleep Mode +#define ILI9341_SLPIN 0x10 +// Sleep Out +#define ILI9341_SLPOUT 0x11 +// Partial Mode ON +#define ILI9341_PTLON 0x12 +// Normal Display Mode ON +#define ILI9341_NORON 0x13 +// Read Display Power Mode +#define ILI9341_RDMODE 0x0A +// Read Display MADCTL +#define ILI9341_RDMADCTL 0x0B +// Read Display Pixel Format +#define ILI9341_RDPIXFMT 0x0C +// Read Display Image Format +#define ILI9341_RDIMGFMT 0x0D +// Read Display Self-Diagnostic Result +#define ILI9341_RDSELFDIAG 0x0F +// Display Inversion OFF +#define ILI9341_INVOFF 0x20 +// Display Inversion ON +#define ILI9341_INVON 0x21 +// Gamma Set +#define ILI9341_GAMMASET 0x26 +// Display OFF +#define ILI9341_DISPOFF 0x28 +// Display ON +#define ILI9341_DISPON 0x29 +// Column Address Set +#define ILI9341_CASET 0x2A +// Page Address Set +#define ILI9341_PASET 0x2B +// Memory Write +#define ILI9341_RAMWR 0x2C +// Memory Read +#define ILI9341_RAMRD 0x2E +// Partial Area +#define ILI9341_PTLAR 0x30 +// Vertical Scrolling Definition +#define ILI9341_VSCRDEF 0x33 +// Memory Access Control +#define ILI9341_MADCTL 0x36 +// Vertical Scrolling Start Address +#define ILI9341_VSCRSADD 0x37 +// COLMOD: Pixel Format Set +#define ILI9341_PIXFMT 0x3A + + + +int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N); +int ili9341_writereg(uint8_t reg, const uint8_t *data, uint32_t N); diff --git a/F3:F303/NitrogenFlooding/spi.c b/F3:F303/NitrogenFlooding/spi.c new file mode 100644 index 0000000..929f9df --- /dev/null +++ b/F3:F303/NitrogenFlooding/spi.c @@ -0,0 +1,114 @@ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hardware.h" +#include "spi.h" + +#include "usb.h" +#ifdef EBUG +#include "strfunc.h" +#endif + +#define SPIDR *((uint8_t*)&SPI2->DR) + +spiStatus spi_status = SPI_NOTREADY; +volatile uint32_t wctr; +#define WAITX(x) do{wctr = 0; while((x) && (++wctr < 360000)) IWDG->KR = IWDG_REFRESH; if(wctr==360000){ DBG("timeout"); return 0;}}while(0) + +// init SPI2 to work with and without DMA +// ILI9341: SCL 0->1; CS=0; command - DC=0, data - DC=1; 1 dummy clock pulse before 24/32 bit data read +// Channel 4 - SPI2 Rx +// Channel 5 - SPI2 Tx +void spi_setup(){ + RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; + // Baudrate = 0b011 - fpclk/16 = 2MHz; software slave management (without hardware NSS pin) + SPI2->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_SSM | SPI_CR1_SSI; + // 8bit; RXNE generates after 8bit of data in FIFO + SPI2->CR2 = SPI_CR2_FRXTH | SPI_CR2_DS_2|SPI_CR2_DS_1|SPI_CR2_DS_0 /*| SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN*/; + spi_status = SPI_READY; + SPI2->CR1 |= SPI_CR1_SPE; +} + +int spi_waitbsy(){ + WAITX(SPI2->SR & SPI_SR_BSY); + return 1; +} + +/** + * @brief spi_send - send data over SPI2 + * @param data - data to read + * @param n - length of data + * @return 0 if failed + */ +int spi_write(const uint8_t *data, uint32_t n){ + if(spi_status != SPI_READY || !data || !n){ + DBG("not ready"); + return 0; + } + for(uint32_t x = 0; x < n; ++x){ + WAITX(!(SPI2->SR & SPI_SR_TXE)); + SPIDR = data[x]; + //WAITX(!(SPI2->SR & SPI_SR_RXNE)); + //(void) SPI2->DR; // clear RXNE after last things + } + return 1; +} + +/** + * @brief spi_send_dma - send data over SPI2 through DMA + * @param data - data to read + * @param n - length of data + * @return 0 if failed + */ +int spi_write_dma(const uint8_t _U_ *data, uint32_t _U_ n){ + if(spi_status != SPI_READY) return 0; + return 0; +} + +/** + * @brief spi_read - read SPI2 data + * @param data - data to read + * @param n - length of data + * @return n + */ +int spi_read(uint8_t _U_ *data, uint32_t _U_ n){ + if(spi_status != SPI_READY){ + DBG("not ready"); + return 0; + } + while(SPI2->SR & SPI_SR_RXNE) (void) SPI2->DR; + for(uint32_t x = 0; x < n; ++x){ + WAITX(!(SPI2->SR & SPI_SR_TXE)); + SPIDR = 0; + WAITX(!(SPI2->SR & SPI_SR_RXNE)); + data[x] = SPI2->DR; + } + return 1; +} + +/** + * @brief spi_read_dma - read SPI2 data through DMA + * @param data - data to read + * @param n - length of data + * @return n + */ +int spi_read_dma(uint8_t _U_ *data, uint32_t _U_ n){ + if(spi_status != SPI_READY) return 0; + return 0; +} + diff --git a/F3:F303/NitrogenFlooding/spi.h b/F3:F303/NitrogenFlooding/spi.h new file mode 100644 index 0000000..e200cde --- /dev/null +++ b/F3:F303/NitrogenFlooding/spi.h @@ -0,0 +1,35 @@ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +typedef enum{ + SPI_NOTREADY, + SPI_READY, + SPI_BUSY +} spiStatus; + +extern spiStatus spi_status; + +void spi_setup(); +int spi_waitbsy(); +int spi_write(const uint8_t *data, uint32_t n); +int spi_write_dma(const uint8_t *data, uint32_t n); +int spi_read(uint8_t *data, uint32_t n); +int spi_read_dma(uint8_t *data, uint32_t n);