mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
[SC64][SW] Added LED I/O blinking persistent setting
This commit is contained in:
parent
9fbff668c7
commit
741e83444e
@ -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 |
|
||||
|
@ -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 |
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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}]')
|
||||
|
Loading…
Reference in New Issue
Block a user