Compare commits
3 Commits
279c7d3c68
...
390528071c
Author | SHA1 | Date |
---|---|---|
true | 390528071c | |
true | 25dc735560 | |
true | 2eda3f2ebb |
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue