Compare commits

..

3 Commits

Author SHA1 Message Date
true 390528071c fix config saving corrupted
was not waiting for eeprom to be ready before trying to write again, causing failure. was also a bug in the write routine.
2024-10-26 20:10:31 -07:00
true 25dc735560 small cleanup and fixes 2024-10-26 19:44:49 -07:00
true 2eda3f2ebb fix "wiggle" name mode; break out rotate for possible future use in other modes 2024-10-26 19:44:34 -07:00
9 changed files with 90 additions and 63 deletions

View File

@ -10,12 +10,12 @@
#include "comm/i2c.h"
uint8_t e16_read_byte(uint16_t addr)
uint8_t eep16_read_byte(uint16_t addr)
{
return 0;
}
void e16_read(uint16_t addr, uint8_t *dat, uint32_t len)
void eep16_read(uint16_t addr, uint8_t *dat, uint32_t len)
{
if (len > EEPROM_SIZE) return;
@ -30,7 +30,7 @@ void e16_read(uint16_t addr, uint8_t *dat, uint32_t len)
i2c_stop();
}
void e16_write(uint16_t addr, uint8_t *dat, uint16_t len)
void eep16_write(uint16_t addr, uint8_t *dat, uint16_t len)
{
uint8_t nack;
@ -45,7 +45,7 @@ void e16_write(uint16_t addr, uint8_t *dat, uint16_t len)
i2c_wr(addr >> 8);
i2c_wr(addr & 0xff);
while (len--) {
while (len--) {
nack = i2c_wr(*dat++);
if (nack) break;
}
@ -53,4 +53,16 @@ void e16_write(uint16_t addr, uint8_t *dat, uint16_t len)
i2c_stop();
}
uint8_t eep16_is_ready()
{
uint8_t ack;
i2c_start();
ack = i2c_wr(EEPROM_I2C_ADDR | 1);
i2c_stop();
if (ack) return 0;
return 1;
}

View File

@ -21,8 +21,9 @@
void e16_read(uint16_t addr, uint8_t *dat, uint32_t len);
void e16_write(uint16_t addr, uint8_t *dat, uint16_t len);
void eep16_read(uint16_t addr, uint8_t *dat, uint32_t len);
void eep16_write(uint16_t addr, uint8_t *dat, uint16_t len);
uint8_t eep16_is_ready();

View File

@ -4,21 +4,19 @@
* main MCU firmware
* 2024 true
*
* much of this code is copied from true's DC29 Whiskey Pirates badge,
* which was in turn copied from the original GAT Nametag.
* Hastily designed and rushed to completion for Supercon 8 on Nov 1, 2024.
*
* The original GAT Nametag used an 8-bit 8051 core MCU.
* Original code was hastily ported to the WP DC29 minibadge.
* This code is again hastily ported, and is based on the DC29 minibadge codebase.
* this is why things are so convoluted.
*
* The GAT Nametag used an 8-bit 8051 core MCU.
* DC29 minibadge used a RISC-V core, and code was hastily ported.
* this is why things like the menu system are so convoluted;
*
* the main MCU is responsible for the following:
* - rendering OLED UI
* - rendering LED programs
* - storing fonts
* - communicating with I2C devices, including:
* - oled display, accelerometer
* - eeprom, sub MCU, RGBLED controller
* - implementing USB interface
* - rendering OLED UI, LED programs
* - storing fonts in flash
* - communicating with I2C devices. includes oled, accelerometer, eeprom, sub MCU, RGBLED
* - implementing USB interface (once I get time)
* - implementing BLE (maybe)
*
*/
@ -43,6 +41,7 @@
#include "user_config.h"
// global settings
#define OLED_UPDATE_RATE 13 // framerate of OLED; { (256*(8/8)) / OLED_UPDATE_RATE }; 13 = 19FPS, 15 = 17FPS
@ -57,7 +56,7 @@
// this was checked with a stopwatch and is close enough
// this value IS FRAMERATE DEPENDENT for some reason... figure it out later
const uint8_t vers[] = "241026a";
const uint8_t vers[] = "241026b";
uint32_t cpu_use = 0;
uint32_t cpu_max = 0;
@ -91,10 +90,13 @@ void ch59x_xtal_conf()
/*
* the CPU will change clockspeed depending on what it is doing.
* all timers are tied to system clock and cannot be derived from the crystal directly,
* except for RTC which can use the LSI. RTC also has a neat feature where it can
* trigger an interrupt when bits match a mask. at this time we're not using the RTC
* for anything else so putting RTC should suffice for our main tick interrupt.
* all hardware timers are tied to system clock and cannot be derived from
* the crystal directly. so we can't rely on timers or systick for timing.
*
* this leaves the RTC as the only periodic interrupt source which uses LSI clk.
* RTC has the capability to trigger an interrupt when count bits match a mask.
* we're not using the RTC for anything else, so RTC interrupt should suffice
* for our main tick interrupt.
*/
__HIGH_CODE
void rtc_reset_trig()
@ -125,6 +127,9 @@ void rtcisr_init()
PFIC_EnableIRQ(RTC_IRQn);
}
/*
* used only for rough cpu usage calculation stuff
*/
void systick_init(void)
{
SysTick->CNT = 0; // clear counter

View File

@ -29,7 +29,7 @@ void menu_tick()
if ((menu == &menu_6) && (menu_idx == 5)) { // about > accelerometer
// accelerometer page never flips
ssd1306_set_flipmirror(0);
} else if (menu != &menu_none) { // nametag
} else if (menu != &menu_none) { // not nametag
if (sysflags & SYS_OLED_ROTATE_X) {
ssd1306_set_flipmirror(1);
} else {

View File

@ -102,6 +102,35 @@ static void menu_none_print_error(uint8_t *err1, uint8_t *err2, uint8_t *err3)
return;
}
__HIGH_CODE
static int8_t rotate_copy(int8_t top, int8_t left, int8_t rot, uint8_t font_idx, uint8_t *txt)
{
int8_t o, w;
// set target buffer, need to do this before width calc
// as this will have the halfwidth bit set appropriately
ssd1306fb_set_target(&rotsrc);
// get left drawing position, so the character is rendered centered
o = ssd1306fb_get_str_width(font_table[font_idx].font, txt, 1, 0);
w = ((rotsrc.width >> 1) - (o >> 1));
// clear buffers before work
ssd1306_cls(&rotdst);
ssd1306_cls(&rotsrc);
// render and rotate
ssd1306fb_set_cursor(w, top);
ssd1306fb_draw_str(font_table[uconf.font_idx].font, txt, 0);
ssd1306fb_rotate(&rotsrc, &rotdst, rot);
// copy dst buffer to oled buffer in correct position
ssd1306fb_set_target(&oled);
ssd1306fb_copy(left - w, 0, ROTATE_TARGET_WIDTH, ROTATE_TARGET_HEIGHT, rotdst.fb);
return o;
}
__HIGH_CODE
void menu_none_disp(uint8_t idx)
{
@ -117,7 +146,7 @@ void menu_none_disp(uint8_t idx)
uint8_t disp_mode;
char txt[6];
char txt[6] = {0};
menu_none_init();
@ -202,13 +231,11 @@ MENU_0_DISP_CHAR_ROTATE:
ssd1306fb_set_color(SSD1306_STATE_SET_PIXEL);
menu_none_set_halfwidth(&rotsrc);
txt[1] = 0;
for (i = 0; i < strlen(uconf.name); i++) {
j = i;
// change character order
if (uconf.nameconf & UCONF_NAME_DISP_MASK) {
if ((uconf.nameconf & UCONF_NAME_DISP_MASK) == UCONF_NAME_DISP_CHAR_ROTATE) {
// this method is a bit jumpy, but works for now
if (sysflags & SYS_OLED_REVERSE_CHARS) {
j = strlen(uconf.name) - i - 1;
@ -217,26 +244,7 @@ MENU_0_DISP_CHAR_ROTATE:
txt[0] = uconf.name[j];
// set target buffer, need to do this before width calc
// as this will have the halfwidth bit set appropriately
ssd1306fb_set_target(&rotsrc);
// get left drawing position, so the character is rendered centered
o = ssd1306fb_get_str_width(font_table[uconf.font_idx].font, txt, 1, 0);
w = ((rotsrc.width >> 1) - (o >> 1));
// clear buffers before work
ssd1306_cls(&rotdst);
ssd1306_cls(&rotsrc);
// render and rotate
ssd1306fb_set_cursor(w, top);
ssd1306fb_draw_str(font_table[uconf.font_idx].font, txt, 0);
ssd1306fb_rotate(&rotsrc, &rotdst, rot);
// copy dst buffer to oled buffer in correct position
ssd1306fb_set_target(&oled);
ssd1306fb_copy(left - w, 0, ROTATE_TARGET_WIDTH, ROTATE_TARGET_HEIGHT, rotdst.fb);
o = rotate_copy(top, left, rot, uconf.font_idx, txt);
// update position of character based on spacing
left += o + uconf.char_spacing;

View File

@ -170,13 +170,13 @@ void menu_1_name_edit()
char txt[10];
ssd1306fb_set_cursor(10, 8);
ssd1306fb_draw_str(font_table[1].font, uconf.name, 0);
ssd1306fb_draw_str(font_DejaVu_Sans_Mono_Bold_11, uconf.name, 0);
ssd1306fb_draw_circle(oled.cursor_x + 4, oled.cursor_y + 7, (mtick & 0x04) ? 2 : 1);
// draw underline
if (edit_mode == EDIT_MODE_IDLE || (edit_mode == EDIT_MODE_EDIT && (mtick & 0x08))) {
x = font_table[1].font[FONT_WIDTH_POS];
x = font_DejaVu_Sans_Mono_Bold_11[FONT_WIDTH_POS];
w = x - 1;
x *= edit_pos;
@ -316,10 +316,10 @@ MENU_0_FONT:
}
}
w = ssd1306fb_get_str_width(font_table[1].font, txt, strlen(txt), 1);
w = ssd1306fb_get_str_width(font_DejaVu_Sans_Mono_Bold_11, txt, strlen(txt), 1);
x = 68 - (w >> 1);
ssd1306fb_set_cursor(x, 18);
ssd1306fb_draw_str(font_table[1].font, txt, 1);
ssd1306fb_draw_str(font_DejaVu_Sans_Mono_Bold_11, txt, 1);
// draw box
ssd1306fb_draw_rect(x - 2, 18, x + w + 2, 31);

View File

@ -91,17 +91,17 @@ void menu_5_disp(uint8_t idx)
break;
}
case LI_FACTORY_RESET: {
// todo: implement manual button checking here
// todo: implement manual button checking here after getting button orientation code working
// yes, this means reset speed depends on framerate lol
if (factory_reset >= 32) {
// do the factory reset
uconf_defaults();
// todo: reboot?
}
ssd1306fb_draw_str(font_table[0].font, "Hold Set to Factory Reset...", 0);
//ssd1306fb_set_color(SSD1306_STATE_CLR_PIXEL);
//ssd1306fb_draw_rect_fill(50, 18, 86, 31);
//ssd1306fb_set_color(SSD1306_STATE_SET_PIXEL);
txt[0] = 0;
ssd1306fb_draw_rect(50, 18, 86, 31);
for (w = 0; w < (factory_reset >> 1); w++) {
ssd1306fb_draw_vline(50 + w, 18, 31);

View File

@ -44,7 +44,7 @@ void uconf_defaults()
if (uconf_flash_offset == 0xf0) {
uconf.iter = 0;
}
uconf.font_idx = 4;
uconf.font_idx = 5;
uconf.char_spacing = 2;
uconf.y_offset = 0;
@ -102,7 +102,7 @@ void uconf_load()
for (i = 0; i < FLASH_RSVD_PAGES; i++) {
// find last page of valid config from flash
uconf_flash_offset = (FLASH_RSVD_PAGES - 1) - i;
e16_read(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES);
eep16_read(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES);
if (!uconf_validate()) {
// valid data
return;
@ -130,8 +130,8 @@ void uconf_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);
// if you need to erase flash, do it here
// we have eeprom so we don't
uconf_flash_offset = 0;
}
@ -145,8 +145,9 @@ void uconf_write()
uaddr = (uint8_t *)&uconf;
while (fsize) {
e16_write(faddr, uaddr, (fsize > 128) ? 128 : fsize);
if (fsize < 128) break;
while (!eep16_is_ready());
eep16_write(faddr, uaddr, (fsize > 128) ? 128 : fsize);
if (fsize <= 128) break;
fsize -= 128;
faddr += 128;
uaddr += 128;

View File

@ -27,7 +27,7 @@
#define SYS_OLED_REVERSE_CHARS (1 << 2) // todo: figure out wtf this is
// user configuration stuff
#define UCONF_VER 0x03
#define UCONF_VER 0x04
#define UCONF_FLAGS_AUTOROTATE_ENA (1 << 0)
#define UCONF_FLAGS_AD_BANNER (1 << 1) // show conference banner text