[SC64][SW] Added LED I/O blinking persistent setting

This commit is contained in:
Mateusz Faderewski 2023-02-10 21:38:49 +01:00
parent 9fbff668c7
commit 741e83444e
13 changed files with 220 additions and 17 deletions

View File

@ -11,6 +11,8 @@
| `B` | **CIC_PARAMS_SET** | cic_params_0 | cic_params_1 | --- | --- | Set CIC disable/mode/seed/checksum |
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
| `C` | **CONFIG_SET** | config_id | new_value | --- | --- | Set config option |
| `a` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting |
| `A` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting |
| `t` | **TIME_GET** | --- | --- | --- | time | Get current RTC value |
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set RTC value |
| `m` | **MEMORY_READ** | address | length | --- | data | Read data from specified memory address |

View File

@ -9,6 +9,8 @@
| `v` | **VERSION_GET** | --- | --- | api_version | --- | Get command API version |
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
| `C` | **CONFIG_SET** | config_id | new_value | --- | previous_value | Set config option and get previous value |
| `c` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
| `C` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting option |
| `t` | **TIME_GET** | --- | --- | time_0 | time_1 | Get current RTC value |
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set RTC value |
| `m` | **USB_READ** | pi_address | length | --- | --- | Receive data from USB to flashcart |

View File

@ -14,6 +14,8 @@
- [`12`: **BUTTON\_STATE**](#12-button_state)
- [`13`: **BUTTON\_MODE**](#13-button_mode)
- [`14`: **ROM\_EXTENDED\_ENABLE**](#14-rom_extended_enable)
- [Supported persistent setting options](#supported-persistent-setting-options)
- [`0`: **LED\_ENABLE**](#0-led_enable)
---
@ -231,3 +233,24 @@ type: *bool* | default: `0`
- `1` - ROM extended PI access is enabled
Use this setting to enable PI access for extended ROM data located inside flash memory.
---
## Supported persistent setting options
These options are similar to config options but state is persisted through power cycles.
| id | name | type | description |
| --- | -------------- | ------ | --------------------------------------------- |
| `0` | **LED_ENABLE** | *bool* | Enables or disables LED I/O activity blinking |
---
### `0`: **LED_ENABLE**
type: *bool* | default: `1`
- `0` - LED I/O activity blinking is disabled
- `1` - LED I/O activity blinking is enabled
Use this setting to enable or disable LED I/O activity blinking.

View File

@ -27,6 +27,8 @@ typedef enum {
SC64_CMD_VERSION_GET = 'v',
SC64_CMD_CONFIG_GET = 'c',
SC64_CMD_CONFIG_SET = 'C',
SC64_CMD_SETTING_GET = 'a',
SC64_CMD_SETTING_SET = 'A',
SC64_CMD_TIME_GET = 't',
SC64_CMD_TIME_SET = 'T',
SC64_CMD_USB_READ = 'm',
@ -126,6 +128,18 @@ void sc64_set_config (sc64_cfg_id_t id, uint32_t value) {
sc64_execute_cmd(SC64_CMD_CONFIG_SET, args, NULL);
}
uint32_t sc64_get_setting (sc64_setting_id_t id) {
uint32_t args[2] = { id, 0 };
uint32_t result[2];
sc64_execute_cmd(SC64_CMD_SETTING_GET, args, result);
return result[1];
}
void sc64_set_setting (sc64_setting_id_t id, uint32_t value) {
uint32_t args[2] = { id, value };
sc64_execute_cmd(SC64_CMD_SETTING_SET, args, NULL);
}
void sc64_get_boot_info (sc64_boot_info_t *info) {
info->boot_mode = (sc64_boot_mode_t) sc64_get_config(CFG_ID_BOOT_MODE);
info->cic_seed = (sc64_cic_seed_t) sc64_get_config(CFG_ID_CIC_SEED);

View File

@ -34,6 +34,10 @@ typedef enum {
CFG_ID_ROM_EXTENDED_ENABLE,
} sc64_cfg_id_t;
typedef enum {
SETTING_ID_LED_ENABLE,
} sc64_setting_id_t;
typedef enum {
DD_MODE_DISABLED = 0,
DD_MODE_REGS = 1,
@ -121,6 +125,8 @@ void sc64_irq_clear (void);
uint32_t sc64_get_config (sc64_cfg_id_t id);
void sc64_set_config (sc64_cfg_id_t id, uint32_t value);
uint32_t sc64_get_setting (sc64_setting_id_t id);
void sc64_set_setting (sc64_setting_id_t id, uint32_t value);
void sc64_get_boot_info (sc64_boot_info_t *info);
void sc64_get_time (sc64_rtc_time_t *t);

View File

@ -32,6 +32,10 @@ typedef enum {
CFG_ID_ROM_EXTENDED_ENABLE,
} cfg_id_t;
typedef enum {
SETTING_ID_LED_ENABLE,
} setting_id_t;
typedef enum {
DD_MODE_DISABLED = 0,
DD_MODE_REGS = 1,
@ -356,6 +360,36 @@ bool cfg_update (uint32_t *args) {
return false;
}
bool cfg_query_setting (uint32_t *args) {
rtc_settings_t settings = (*rtc_get_settings());
switch (args[0]) {
case SETTING_ID_LED_ENABLE:
args[1] = settings.led_enabled;
break;
default:
return true;
}
return false;
}
bool cfg_update_setting (uint32_t *args) {
rtc_settings_t settings = (*rtc_get_settings());
switch (args[0]) {
case SETTING_ID_LED_ENABLE:
settings.led_enabled = args[1];
break;
default:
return true;
}
rtc_set_settings(&settings);
return false;
}
bool cfg_set_rom_write_enable (bool value) {
uint32_t scr = fpga_reg_get(REG_CFG_SCR);
cfg_change_scr_bits(CFG_SCR_ROM_WRITE_ENABLED, value);
@ -447,6 +481,20 @@ void cfg_process (void) {
args[1] = prev_cfg[1];
break;
case 'a':
if (cfg_query_setting(args)) {
cfg_set_error(CFG_ERROR_BAD_CONFIG_ID);
return;
}
break;
case 'A':
if (cfg_update_setting(args)) {
cfg_set_error(CFG_ERROR_BAD_CONFIG_ID);
return;
}
break;
case 't':
cfg_get_time(args);
break;

View File

@ -19,6 +19,8 @@ typedef enum {
uint32_t cfg_get_version (void);
bool cfg_query (uint32_t *args);
bool cfg_update (uint32_t *args);
bool cfg_query_setting (uint32_t *args);
bool cfg_update_setting (uint32_t *args);
bool cfg_set_rom_write_enable (bool value);
save_type_t cfg_get_save_type (void);
void cfg_get_time (uint32_t *args);

View File

@ -318,7 +318,7 @@ static void cic_soft_reset_timeout (void) {
static void cic_soft_reset (void) {
cic_read();
hw_tim_setup(TIM_ID_CIC, 550, cic_soft_reset_timeout);
hw_tim_setup(TIM_ID_CIC, 500, cic_soft_reset_timeout);
task_yield();
}
@ -367,7 +367,7 @@ void cic_task (void) {
cic_write_id(region);
hw_tim_setup(TIM_ID_CIC, 1000, cic_write_id_failed);
hw_tim_setup(TIM_ID_CIC, 100, cic_write_id_failed);
cic_write_seed();
hw_tim_stop(TIM_ID_CIC);

View File

@ -1,6 +1,7 @@
#include <stdbool.h>
#include "hw.h"
#include "led.h"
#include "rtc.h"
#include "task.h"
#include "timer.h"
@ -26,16 +27,29 @@ static void led_task_resume (void) {
task_set_ready(TASK_ID_LED);
}
static void led_set_state (bool state, bool force) {
rtc_settings_t *settings = rtc_get_settings();
if (settings->led_enabled || force) {
if (state) {
hw_gpio_set(GPIO_ID_LED);
} else {
hw_gpio_reset(GPIO_ID_LED);
}
} else {
hw_gpio_reset(GPIO_ID_LED);
}
}
static void led_update_error_mode (void) {
if (error_mode) {
if (!(cic_error || rtc_error)) {
hw_gpio_reset(GPIO_ID_LED);
led_set_state(false, true);
error_mode = false;
act_timer = 0;
}
} else {
if (cic_error || rtc_error) {
hw_gpio_reset(GPIO_ID_LED);
led_set_state(false, true);
error_mode = true;
error_timer = 0;
}
@ -58,10 +72,10 @@ static void led_process_errors (void) {
if (error_timer >= LED_ERROR_TICKS_PERIOD) {
uint32_t error_cycle = (error_timer % LED_ERROR_TICKS_PERIOD);
if (error_cycle == LED_ERROR_TICKS_ON) {
hw_gpio_set(GPIO_ID_LED);
led_set_state(true, true);
}
if (error_cycle == 0) {
hw_gpio_reset(GPIO_ID_LED);
led_set_state(false, true);
}
}
}
@ -78,10 +92,10 @@ static void led_process_act (void) {
if (act_timer > 0) {
act_timer -= 1;
if (act_timer == LED_ACT_TICKS_ON) {
hw_gpio_set(GPIO_ID_LED);
led_set_state(true, false);
}
if (act_timer == 0) {
hw_gpio_reset(GPIO_ID_LED);
led_set_state(false, false);
}
}
}

View File

@ -18,15 +18,17 @@
#define RTC_ADDRESS_OSCTRIM (0x08)
#define RTC_ADDRESS_SRAM_MAGIC (0x20)
#define RTC_ADDRESS_SRAM_REGION (0x24)
#define RTC_ADDRESS_SRAM_VERSION (0x28)
#define RTC_ADDRESS_SRAM_SETTINGS (0x2C)
#define RTC_RTCSEC_ST (1 << 7)
#define RTC_RTCWKDAY_VBATEN (1 << 3)
#define RTC_RTCWKDAY_OSCRUN (1 << 5)
#define RTC_SETTINGS_VERSION (1)
static uint8_t rtc_region = 0xFF;
static volatile bool rtc_region_pending = false;
static rtc_time_t rtc_time = {
.second = 0x00,
.minute = 0x00,
@ -39,6 +41,14 @@ static rtc_time_t rtc_time = {
static bool rtc_time_valid = false;
static volatile bool rtc_time_pending = false;
static uint8_t rtc_region = 0xFF;
static volatile bool rtc_region_pending = false;
static rtc_settings_t rtc_settings = {
.led_enabled = true,
};
static volatile bool rtc_settings_pending = false;
static const uint8_t rtc_regs_bit_mask[7] = {
0b01111111,
0b01111111,
@ -151,10 +161,19 @@ static void rtc_write_region (void) {
rtc_write(RTC_ADDRESS_SRAM_REGION, &rtc_region, 1);
}
static void rtc_read_settings (void) {
rtc_read(RTC_ADDRESS_SRAM_SETTINGS, (uint8_t *) (&rtc_settings), sizeof(rtc_settings));
}
static void rtc_write_settings (void) {
rtc_write(RTC_ADDRESS_SRAM_SETTINGS, (uint8_t *) (&rtc_settings), sizeof(rtc_settings));
}
static void rtc_init (void) {
bool uninitialized = false;
const char *magic = "SC64";
uint8_t buffer[4];
uint32_t settings_version;
rtc_read(RTC_ADDRESS_SRAM_MAGIC, buffer, 4);
@ -172,6 +191,14 @@ static void rtc_init (void) {
rtc_write_time();
rtc_write_region();
}
rtc_read(RTC_ADDRESS_SRAM_VERSION, (uint8_t *) (&settings_version), 4);
if (uninitialized || (settings_version != RTC_SETTINGS_VERSION)) {
settings_version = RTC_SETTINGS_VERSION;
rtc_write(RTC_ADDRESS_SRAM_VERSION, (uint8_t *) (&settings_version), 4);
rtc_write_settings();
}
}
@ -222,10 +249,24 @@ void rtc_set_region (uint8_t region) {
rtc_region_pending = true;
}
rtc_settings_t *rtc_get_settings (void) {
return (&rtc_settings);
}
void rtc_set_settings (rtc_settings_t *settings) {
hw_tim_disable_irq(TIM_ID_LED);
rtc_settings = *settings;
rtc_settings_pending = true;
hw_tim_enable_irq(TIM_ID_LED);
}
void rtc_task (void) {
rtc_init();
rtc_read_region();
rtc_read_settings();
while (1) {
if (rtc_time_pending) {
@ -238,6 +279,11 @@ void rtc_task (void) {
rtc_write_region();
}
if (rtc_settings_pending) {
rtc_settings_pending = false;
rtc_write_settings();
}
rtc_read_time();
hw_tim_setup(TIM_ID_RTC, 50, rtc_task_resume);

View File

@ -7,20 +7,26 @@
typedef struct {
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t weekday;
uint8_t day;
uint8_t month;
uint8_t year;
volatile uint8_t second;
volatile uint8_t minute;
volatile uint8_t hour;
volatile uint8_t weekday;
volatile uint8_t day;
volatile uint8_t month;
volatile uint8_t year;
} rtc_time_t;
typedef struct {
volatile bool led_enabled;
} rtc_settings_t;
bool rtc_get_time (rtc_time_t *time);
void rtc_set_time (rtc_time_t *time);
uint8_t rtc_get_region (void);
void rtc_set_region (uint8_t region);
rtc_settings_t *rtc_get_settings (void);
void rtc_set_settings (rtc_settings_t *settings);
void rtc_task (void);
void rtc_process (void);

View File

@ -189,6 +189,20 @@ static void usb_rx_process (void) {
p.response_pending = true;
break;
case 'a':
p.response_error = cfg_query_setting(p.rx_args);
p.rx_state = RX_STATE_IDLE;
p.response_pending = true;
p.response_info.data_length = 4;
p.response_info.data[0] = p.rx_args[1];
break;
case 'A':
p.response_error = cfg_update_setting(p.rx_args);
p.rx_state = RX_STATE_IDLE;
p.response_pending = true;
break;
case 't':
cfg_get_time(p.rx_args);
p.rx_state = RX_STATE_IDLE;

View File

@ -243,6 +243,9 @@ class SC64:
BUTTON_MODE = 13
ROM_EXTENDED_ENABLE = 14
class __SettingId(IntEnum):
LED_ENABLE = 0
class __UpdateError(IntEnum):
OK = 0
TOKEN = 1
@ -342,6 +345,19 @@ class SC64:
raise ValueError(f'Could not get config {config.name}')
return self.__get_int(data)
def __set_setting(self, setting: __SettingId, value: int) -> None:
try:
self.__link.execute_cmd(cmd=b'A', args=[setting, value])
except ConnectionException:
raise ValueError(f'Could not set setting {setting.name} to {value:08X}')
def __get_setting(self, setting: __SettingId) -> int:
try:
data = self.__link.execute_cmd(cmd=b'a', args=[setting, 0])
except ConnectionException:
raise ValueError(f'Could not get setting {setting.name}')
return self.__get_int(data)
def __write_memory(self, address: int, data: bytes) -> None:
if (len(data) > 0):
self.__link.execute_cmd(cmd=b'M', args=[address, len(data)], data=data, timeout=20.0)
@ -424,6 +440,7 @@ class SC64:
'button_state': bool(self.__get_config(self.__CfgId.BUTTON_STATE)),
'button_mode': self.__ButtonMode(self.__get_config(self.__CfgId.BUTTON_MODE)),
'rom_extended_enable': bool(self.__get_config(self.__CfgId.ROM_EXTENDED_ENABLE)),
'led_enable': bool(self.__get_setting(self.__SettingId.LED_ENABLE)),
}
def debug_send(self, datatype: __DebugDatatype, data: bytes) -> None:
@ -531,6 +548,9 @@ class SC64:
self.__link.execute_cmd(cmd=b'B', args=[self.__get_int(data[0:4]), self.__get_int(data[4:8])])
return (seed, checksum)
def set_led_enable(self, enabled: bool) -> None:
self.__set_setting(self.__SettingId.LED_ENABLE, enabled)
def update_firmware(self, data: bytes, status_callback: Optional[Callable[[str], None]]=None) -> None:
address = self.__Address.FIRMWARE
self.__write_memory(address, data)
@ -816,6 +836,7 @@ if __name__ == '__main__':
parser.add_argument('--update-bootloader', metavar='file', help='update SC64 bootloader (not recommended, use --update-firmware instead)')
parser.add_argument('--reset-state', action='store_true', help='reset SC64 internal state')
parser.add_argument('--print-state', action='store_true', help='print SC64 internal state')
parser.add_argument('--led-enabled', metavar='{true,false}', help='disable or enable LED I/O activity blinking')
parser.add_argument('--boot', type=SC64.BootMode, action=EnumAction, help='set boot mode')
parser.add_argument('--tv', type=SC64.TVType, action=EnumAction, help='force TV type to set value')
parser.add_argument('--cic', type=SC64.CICSeed, action=EnumAction, help='force CIC seed to set value')
@ -874,6 +895,11 @@ if __name__ == '__main__':
value = getattr(value, 'name')
print(f' {key}: {value}')
if (args.led_enabled != None):
value = (args.led_enabled == 'true')
sc64.set_led_enable(value)
print(f'LED blinking set to [{"ENABLED" if value else "DISABLED"}]')
if (args.boot != None):
sc64.set_boot_mode(args.boot)
print(f'Boot mode set to [{args.boot.name}]')