Compare commits

...

3 Commits

Author SHA1 Message Date
true 8a5e11592c add vendor accelerometer library
vendor accelerometer library is added, and initial code to use it has also been adapted from an example. this is incomplete; need to implement interrupts if using them. for now this may be just enough to work in polled mode.
2024-10-15 04:24:45 -07:00
true caaa30d67e more menu fixups 2024-10-15 04:23:17 -07:00
true d33cc2f775 add eeprom support, user config loading 2024-10-15 04:23:00 -07:00
23 changed files with 4660 additions and 70 deletions

View File

@ -10,6 +10,9 @@
#include "global.h"
#ifdef SOFT_I2C_MASTER
@ -17,9 +20,9 @@
#define i2c_init() i2cm_init()
#define i2c_start() SetSysClock(CLK_SOURCE_PLL_32MHz); i2cm_start()
#define i2c_start() SetSysClock(SYSCLK_FREQ_USEI2C); i2cm_start()
#define i2c_restart() i2cm_restart()
#define i2c_stop() SetSysClock(CLK_SOURCE_HSE_16MHz); i2cm_stop()
#define i2c_stop() SetSysClock(SYSCLK_FREQ_NORMAL); i2cm_stop()
#define i2c_rd(ack) i2cm_rd(ack)
#define i2c_wr(dat) i2cm_wr(dat)
#define i2c_addr(a, w) i2c_start(); i2cm_addr(a, w)

View File

@ -123,7 +123,7 @@ uint8_t i2cm_wr(uint8_t dat)
for (x = 8; x; x--) {
if (dat & 0x80) { SDA_IN_HI(); SCL_IN_HI(); wr_delay_hi(); }
else { SDA_OUTLO(); SCL_OUTLO(); wr_delay_lo(); }
else { SDA_OUTLO(); SCL_OUTLO(); wr_delay_lo(); }
dat <<= 1;
SCL_OUTLO();
@ -149,7 +149,7 @@ uint8_t i2cm_addr(uint8_t addr, uint8_t reading_bit)
void i2cm_rdbuf(uint8_t *dat, uint8_t len)
{
while(len--) *dat++ = i2cm_rd(len > 0);
while (len--) *dat++ = i2cm_rd(len > 0);
// i2cm_stop();
}
@ -157,7 +157,7 @@ void i2cm_wrbuf(const uint8_t *dat, uint8_t len)
{
uint8_t nack;
while(len--) {
while (len--) {
nack = i2cm_wr(*dat++);
if (nack) break;
}

View File

@ -12,6 +12,11 @@
#define SYSCLK_FREQ_NORMAL CLK_SOURCE_HSE_16MHz
#define SYSCLK_FREQ_USEI2C CLK_SOURCE_PLL_32MHz
extern const uint8_t vers[];
extern uint8_t cpu_use;

View File

@ -1,8 +1,56 @@
/*
* eeprom16.c
*
* Created on: Oct 11, 2024
* Author: true
* code to interface with 16-bit addressed I2C EEPROMs
* tested up to max size of 512Kbit (64Kbyte)
*
*/
#include "eeprom16.h"
#include "comm/i2c.h"
uint8_t e16_read_byte(uint16_t addr)
{
return 0;
}
void e16_read(uint16_t addr, uint8_t *dat, uint32_t len)
{
if (len > EEPROM_SIZE) return;
i2c_start();
i2c_addr(EEPROM_I2C_ADDR, 0);
i2c_wr(addr >> 8);
i2c_wr(addr & 0xff);
i2c_restart();
i2c_addr(EEPROM_I2C_ADDR, 1);
while (len--) *dat++ = i2cm_rd(len > 0);
i2c_stop();
}
void e16_write(uint16_t addr, uint8_t *dat, uint16_t len)
{
uint8_t nack;
// this function can only write one page at a time
if (len > EEPROM_PAGE_SIZE) return;
// this function does not detect page boundaries.
// it is your responsibility to correctly address for
// page boundaries. most eeprom roll over page boundaries.
i2c_start();
i2c_addr(EEPROM_I2C_ADDR, 0);
i2c_wr(addr >> 8);
i2c_wr(addr & 0xff);
while (len--) {
nack = i2cm_wr(*dat++);
if (nack) break;
}
}

View File

@ -10,4 +10,20 @@
#include <stdint.h>
#define EEPROM_I2C_ADDR 0xa0
#define EEPROM_SIZE 65536
#define EEPROM_PAGE_SIZE 128
void e16_read(uint16_t addr, uint8_t *dat, uint32_t len);
void e16_write(uint16_t addr, uint8_t *dat, uint16_t len);
#endif /* USER_DEVICE_EEPROM16_H_ */

View File

@ -1,8 +0,0 @@
/*
* lis2dw.c
*
* Created on: Oct 11, 2024
* Author: true
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/*
* lis2dw.c
*
* Created on: Oct 11, 2024
* Author: true
*/
#include "lis2dw_i2c.h"
#include <stdint.h>
void lis2dw_init()
{
uint8_t buf[2];
/*
buf[0] = ADXL345_REG_DATAX0 | ADXL345_MODE_RD | ADXL345_MODE_MB;
memset(&buf[1], 0x00, 6);
lis2dw_i2c_write(LIS2DW_I2C_ADDR);
adxl_spi_xfer(ADXL345_SPI_DEV, buf, buf, 7);
*/
}
void lis2dw_set_power_mode(uint8_t mode)
{
}
void lis2dw_read_axes(uint16_t *x, uint16_t *y, uint16_t *z)
{
uint8_t buf[6];
buf[0] = LIS2DW_REG_OUT_X_L;
lis2dw_i2c_write(LIS2DW_I2C_ADDR, buf, 1);
lis2dw_i2c_read(LIS2DW_I2C_ADDR, buf, 6);
*x = buf[0] | buf[1] << 8;
*y = buf[2] | buf[3] << 8;
*z = buf[4] | buf[5] << 8;
}

View File

@ -9,9 +9,18 @@
#define USER_HW_LIS2DW_H_
#include "comm/i2c.h"
#define LIS2DW_I2C_ADDR 0x30
#define LIS2DW_I2C_ADDR_SDO_LOW 0x32
#define lis2dw_i2c_read(a, d, s) i2c_read(a, d, s);
#define lis2dw_i2c_write(a, d, s) i2c_write(a, d, s);
// driver constants
#define LIS2DW_ADDR 0x30
#define LIS2DW_ADDR_SDO_LOW 0x31
// registers
#define LIS2DW_REG_OUT_T_L 0x0d
@ -56,25 +65,31 @@
// register properties
#define LIS2DW_WHO_AM_I 0x44
#define LIS2DW_CTRL1_LP_MODE1 (0 << 0)
#define LIS2DW_CTRL1_LP_MODE2 (1 << 0)
#define LIS2DW_CTRL1_LP_MODE3 (2 << 0)
#define LIS2DW_CTRL1_LP_MODE4 (3 << 0)
#define LIS2DW_CTRL1_LP_MODE_SHIFT 0
enum LIS2DW_CTRL1_LP_Mode {
LIS2DW_CTRL1_LP_MODE1 = 0,
LIS2DW_CTRL1_LP_MODE2,
LIS2DW_CTRL1_LP_MODE3,
LIS2DW_CTRL1_LP_MODE4
};
#define LIS2DW_CTRL1_MODE_LO_POWR (0 << 2)
#define LIS2DW_CTRL1_MODE_HI_PERF (1 << 2)
#define LIS2DW_CTRL1_MODE_SNGL_DATA (2 << 2)
#define LIS2DW_CTRL1_DATA_RATE_PWR_DOWN (0 << 4)
#define LIS2DW_CTRL1_DATA_RATE_1_6 (1 << 4) // 12.5 in high power mode
#define LIS2DW_CTRL1_DATA_RATE_12_5 (2 << 4)
#define LIS2DW_CTRL1_DATA_RATE_25 (3 << 4)
#define LIS2DW_CTRL1_DATA_RATE_50 (4 << 4)
#define LIS2DW_CTRL1_DATA_RATE_100 (5 << 4)
#define LIS2DW_CTRL1_DATA_RATE_200 (6 << 4)
#define LIS2DW_CTRL1_DATA_RATE_400 (7 << 4) // 200 in low power mode
#define LIS2DW_CTRL1_DATA_RATE_800 (8 << 4) // 200 in low power mode
#define LIS2DW_CTRL1_DATA_RATE_1600 (9 << 4) // 200 in low power mode
#define LI22DW_CTRL1_DATA_RATE_SHIFT 4
enum LIS2DW_CTRL1_Data_Rate {
LIS2DW_CTRL1_DATA_RATE_PWR_DOWN = 0,
LIS2DW_CTRL1_DATA_RATE_1_6, // 12.5 in high power mode
LIS2DW_CTRL1_DATA_RATE_12_5,
LIS2DW_CTRL1_DATA_RATE_25,
LIS2DW_CTRL1_DATA_RATE_50,
LIS2DW_CTRL1_DATA_RATE_100,
LIS2DW_CTRL1_DATA_RATE_200,
LIS2DW_CTRL1_DATA_RATE_400, // 200 in low power mode
LIS2DW_CTRL1_DATA_RATE_800, // 200 in low power mode
LIS2DW_CTRL1_DATA_RATE_1600 // 200 in low power mode
};
#define LIS2DW_CTRL2_SPI_4_WIRE (0 << 0)
#define LIS2DW_CTRL2_SPI_3_WIRE (1 << 0)

View File

@ -15,7 +15,7 @@
#include "rgbled.h"
#include "hw/lis2dw.h"
#include "misc/accel.h"
#include "../misc/intscale.h"
#include "../misc/sin7.h"

View File

@ -26,14 +26,33 @@
#include <hw/ch32sub.h>
#include "CH59x_common.h"
#include "port_intr.h"
#include "comm/i2c.h"
#include "hw/gat/gat_gpio.h"
#include "led/rgbled.h"
#include "misc/accel.h"
#include "global.h"
#include "port_intr.h"
#include "user_config.h"
const uint8_t vers[] = "241013.01";
uint8_t cpu_use = 0;
uint8_t cpu_max = 0;
uint32_t uptime = 0;
uint16_t uptime_hour;
uint8_t uptime_min;
uint8_t uptime_sec;
uint32_t idle_time_menu;
uint32_t idle_time_still;
uint8_t idle_go_sleep;
@ -47,33 +66,43 @@ int main()
{
// configure clock
ch59x_xtal_conf();
SetSysClock(CLK_SOURCE_PLL_32MHz);
SetSysClock(SYSCLK_FREQ_USEI2C);
// enable DC-DC converter; brings significant power saving
PWR_DCDCCfg(ENABLE);
// get i2c up and running
// get i2c initialized since most stuff will need it
i2c_init();
// decrease clock speed when not using i2c
SetSysClock(CLK_SOURCE_HSE_16MHz);
// read the user config
uconf_load();
// configure port-based interrupts (used for chsub interrupt, mainly)
port_intr_init();
// configure aux MCU initial settings, attention interrupt
// initialize aux MCU
ch32sub_init();
// and enable RGBLED controller hardware pin so the controller can wake up
ch32sub_rgb_hwen(1);
// configure RGBLED controller
// initialize accelerometer
accel_init();
// initialize RGBLED controller
rgbled_init();
// configure GAT aux GPIOs, get gat ID
gat_gpio_init();
// configure GAT i2c slave
// not yet implemented
// configure port-based interrupts (used for ch32sub interrupt)
port_intr_init();
// note that system clock speed is decreased after every use of I2C
while(1) {
// only care about aux MCU when all other processing is done
ch32sub_process();
// sleep when we're doing nothing
__WFI();
}
}

View File

@ -7,8 +7,12 @@
#include "accel.h"
#include "hw/lis2dw12_reg.h"
#include "comm/i2c.h"
// user data
AccelData accel;
AccelData accel_last[4];
AccelData accel_smoothing;
@ -16,6 +20,59 @@ AccelData accel_smoothing;
int16_t movement;
// hardware
static stmdev_ctx_t dev_ctx;
int32_t accel_i2c_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len)
{
(void)(handle);
i2c_write_reg8(LIS2DW_I2C_ADDR, reg, bufp, len);
return 0;
}
int32_t accel_i2c_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
{
(void)(handle);
i2c_read_reg8(LIS2DW_I2C_ADDR, reg, bufp, len);
return 0;
}
void accel_init()
{
uint8_t devid;
uint8_t reset;
dev_ctx.write_reg = accel_i2c_write;
dev_ctx.read_reg = accel_i2c_read;
// make sure we've got the right device
lis2dw12_device_id_get(&dev_ctx, &devid);
if (devid != LIS2DW12_ID) {
while (1) {
// might as well crash the user's badge
}
}
// reset accelerometer
lis2dw12_reset_set(&dev_ctx, PROPERTY_ENABLE);
do {
lis2dw12_reset_get(&dev_ctx, &reset);
} while (reset);
// configure scale, power mode
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);
lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_SINGLE_LOW_PWR_LOW_NOISE_4);
// configure output data rate
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_100Hz);
}
int8_t accel_get_rotation()
{

View File

@ -13,6 +13,11 @@
#define LIS2DW_I2C_ADDR 0x30
#define LIS2DW_I2C_ADDR_SDO_LOW 0x32
typedef struct AccelData {
int16_t x;
int16_t y;
@ -26,6 +31,8 @@ extern uint16_t movement_worst;
void accel_init();
int8_t accel_get_rotation();
int16_t accel_get_movement();

View File

@ -1,5 +1,5 @@
/*
* $Id: menu_base.c 500 2021-08-08 19:43:38Z true $
* menu_base.c
* begin 20190527 true
*/
@ -41,7 +41,7 @@ void menu_tick()
void menu_start(uint8_t x)
{
x = x;
(void)(x);
menu = (MenuItem *)&menu_0;
menu_idx = 0;
@ -53,7 +53,7 @@ void menu_start(uint8_t x)
void menu_stop(uint8_t x)
{
x = x;
(void)(x);
menu = (MenuItem *)&menu_none;

View File

@ -1,5 +1,5 @@
/*
* $Id: menu_def.c 499 2021-07-26 05:24:02Z true $
* menu_def.c
* begin 20190527 true
*
* main menu

View File

@ -1,5 +1,5 @@
/*
* $Id: menu_entry_0.c 494 2021-07-21 11:46:11Z true $
* menu_entry_0.c
* begin 20190527 true
*
* main menu functions
@ -106,8 +106,6 @@ void menu_none_disp(uint8_t idx)
char txt[6];
(idx = idx);
menu_none_init();
// total width and left / starting boundary

View File

@ -1,5 +1,5 @@
/*
* $Id: menu_entry_1.c 494 2021-07-21 11:46:11Z true $
* menu_entry_1.c
* begin 20190612 true
*
* name setup menu functions

View File

@ -1,5 +1,5 @@
/*
* $Id: menu_entry_2.c 495 2021-07-22 20:53:39Z true $
* menu_entry_2.c
* begin 20190612 true
*
* led setup menu functions

View File

@ -1,5 +1,5 @@
/*
* $Id: menu_entry_3.c 494 2021-07-21 11:46:11Z true $
* menu_entry_3.c
* begin 20200807 true
*
* snek

View File

@ -1,5 +1,5 @@
/*
* $Id: menu_entry_5.c 499 2021-07-26 05:24:02Z true $
* menu_entry_5.c
* begin 20190613 true
*
* settings menu functions

View File

@ -1,5 +1,5 @@
/*
* $Id: menu_entry_6.c 500 2021-08-08 19:43:38Z true $
* menu_entry_6.c
* begin 20190527 true
*
* about menu functions

View File

@ -73,14 +73,14 @@ static void uconf_defaults()
static int8_t uconf_validate()
{
// blank check
if (uconf.checksum == 0xffff) return -1;
// version check
if (uconf.ver != UCONF_VER) {
return -1;
return -2;
}
// blank check
if (uconf.checksum == 0xffff) return -2;
// checksum verify
if (!checksum_verify((uint8_t *)&uconf, sizeof(uconf) - 2, uconf.checksum)) {
return -3;
@ -96,20 +96,16 @@ void uconf_load()
{
uint8_t i;
w25q_power_up();
for (i = 0; i < FLASH_RSVD_PAGES; i++) {
// find last page of valid config from flash
uconf_flash_offset = (FLASH_RSVD_PAGES - 1) - i;
w25q_read(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES);
e16_read(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES);
if (!uconf_validate()) {
// valid data
return;
}
}
w25q_power_down();
// flash has no valid data whatsoever
// don't worry about flash setup; that is done during writing
uconf_flash_offset = 0xf0;
@ -118,16 +114,22 @@ void uconf_load()
void uconf_write()
{
eclic_global_interrupt_disable();
uint32_t intr;
w25q_power_up();
uint16_t fsize;
uint16_t faddr;
uint8_t *uaddr;
SYS_DisableAllIrq(&intr);
// track writes and set up next page to write
uconf.iter++;
uconf_flash_offset++;
if (uconf_flash_offset >= FLASH_RSVD_PAGES) {
// we need to erase flash and start writing at the beginning
w25q_erase_sector(0x000000, 1);
// w25q_erase_sector(0x000000, 1);
uconf_flash_offset = 0;
}
@ -135,9 +137,17 @@ void uconf_write()
uconf.checksum = checksum_gen((uint8_t *)&uconf, sizeof(uconf) - 2);
// write config data
w25q_write(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES);
fsize = FLASH_UCONF_BYTES;
faddr = uconf_flash_offset * FLASH_UCONF_BYTES;
uaddr = (uint8_t *)&uconf;
w25q_power_down();
while (fsize) {
e16_write(faddr, uaddr, (fsize > 128) ? 128 : fsize);
if (fsize < 128) break;
fsize -= 128;
faddr += 128;
uaddr += 128;
}
eclic_global_interrupt_enable();
SYS_RecoverIrq(intr);
}