Skip to content

Commit 03c4bb7

Browse files
committed
[CX II] Implement sleep mode
With this, it's possible to turn the calculator back on after it went into sleep mode (idle timeout or explicitly turned off). What happens when pressing On is that the calc starts from bootrom again, but that finds fastboot data in the 90030000 area left by the OS and uses that to validate some state and jumps back to the OS code in SDRAM. Add a TODO entry to improve fastboot data handling. Currently the data is preserved across restarts, which means that some possibly incompatible bootrom tries to interpret it. So far the validation detects that SDRAM was cleared and aborts.
1 parent 5c81aa3 commit 03c4bb7

File tree

8 files changed

+36
-2
lines changed

8 files changed

+36
-2
lines changed

TODO.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
* Better debugger integration
1414
* Don't use a 60Hz timer for LCD redrawing, hook lcd_event instead
1515
* Less global vars (emu.h), move into structs
16-
* Use streams for reading/writing snapshots instead of struct emu_snapshot
16+
* Use streams for reading/writing snapshots instead of struct emu_snapshot
17+
* Fastboot data is currently not cleared at all, it survives soft and hard
18+
resets as well as restarts. This was the simplest way to get installers to
19+
work, which require that state is persisted across software resets. Ideally,
20+
fastboot data is cleared on hardware resets and restarts.
1721

1822
##Wishlist:
1923
* Skin loader/switcher

core/cpu.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,17 @@ void set_reg_bx(uint8_t i, uint32_t value)
432432
}
433433
}
434434

435+
void cpu_reset()
436+
{
437+
memset(&arm, 0, sizeof arm);
438+
arm.control = 0x00050078;
439+
arm.cpsr_low28 = MODE_SVC | 0xC0;
440+
cpu_events &= EVENT_DEBUG_STEP;
441+
442+
addr_cache_flush();
443+
flush_translations();
444+
}
445+
435446
bool cpu_resume(const emu_snapshot *s)
436447
{
437448
return snapshot_read(s, &arm, sizeof(arm))

core/cpu.h

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ extern struct arm_state arm __asm__("arm");
8484
#endif
8585

8686
typedef struct emu_snapshot emu_snapshot;
87+
void cpu_reset(); // Essentially a soft reset
8788
bool cpu_resume(const emu_snapshot *s);
8889
bool cpu_suspend(emu_snapshot *s);
8990
void cpu_int_check();

core/cx2.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void aladdin_pmu_write(uint32_t addr, uint32_t value)
7777
if(value & 2)
7878
{
7979
/* enter sleep, jump to 0 when On pressed. */
80-
warn("Sleep not implemented");
80+
cpu_events |= EVENT_SLEEP;
8181
// Without this, the clocks are wrong
8282
aladdin_pmu_reset();
8383
}

core/emu.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,12 @@ void emu_loop(bool reset)
348348
goto reset;
349349
}
350350

351+
if (cpu_events & EVENT_SLEEP) {
352+
assert(emulate_cx2);
353+
cycle_count_delta = 0;
354+
break;
355+
}
356+
351357
if (cpu_events & (EVENT_FIQ | EVENT_IRQ)) {
352358
// Align PC in case the interrupt occurred immediately after a jump
353359
if (arm.cpsr_low28 & 0x20)

core/emu.h

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ extern uint32_t cpu_events __asm__("cpu_events");
3333
#define EVENT_RESET 4
3434
#define EVENT_DEBUG_STEP 8
3535
#define EVENT_WAITING 16
36+
#define EVENT_SLEEP 32
3637

3738
// Settings
3839
extern bool exiting, debug_on_start, debug_on_warn, print_on_warn;

core/keypad.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ void keypad_on_pressed() {
3333
// TODO: The CX II may have an enable bit somewhere
3434
if(!emulate_cx2 && pmu.on_irq_enabled)
3535
int_set(INT_POWER, true);
36+
37+
if(cpu_events & EVENT_SLEEP) {
38+
assert(emulate_cx2);
39+
cpu_reset();
40+
}
3641
}
3742

3843
uint32_t keypad_read(uint32_t addr) {

core/misc.c

+6
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,15 @@ void timer_reset() {
245245
static fastboot_state fastboot;
246246

247247
uint32_t fastboot_cx_read(uint32_t addr) {
248+
if((addr & 0xFFFF) >= 0x1000)
249+
return bad_read_word(addr); // On HW it repeats
250+
248251
return fastboot.mem[(addr & 0xFFF) >> 2];
249252
}
250253
void fastboot_cx_write(uint32_t addr, uint32_t value) {
254+
if((addr & 0xFFFF) >= 0x1000)
255+
return bad_write_word(addr, value);
256+
251257
// TODO: This isn't cleared on resets, but should be cleared
252258
// eventually, probably on restarts?
253259
fastboot.mem[(addr & 0xFFF) >> 2] = value;

0 commit comments

Comments
 (0)