#include #include #include volatile uint8_t __xdata __at(0x103B) ECINDAR0; volatile uint8_t __xdata __at(0x103C) ECINDAR1; volatile uint8_t __xdata __at(0x103D) ECINDAR2; volatile uint8_t __xdata __at(0x103E) ECINDAR3; volatile uint8_t __xdata __at(0x103F) ECINDDR; volatile uint8_t __xdata __at(0x1F01) ETWCFG; volatile uint8_t __xdata __at(0x1F07) EWDKEYR; uint8_t acpi_read(uint8_t addr) { uint8_t data = 0; switch (addr) { case 4: data = ECINDAR0; break; case 5: data = ECINDAR1; break; case 6: data = ECINDAR2; break; case 7: data = ECINDAR3; break; case 8: data = ECINDDR; break; } return data; } void acpi_write(uint8_t addr, uint8_t data) { switch (addr) { case 4: ECINDAR0 = data; break; case 5: ECINDAR1 = data; break; case 6: ECINDAR2 = data; break; case 7: ECINDAR3 = data; break; case 8: ECINDDR = data; break; } } enum PmcState { PMC_STATE_DEFAULT, PMC_STATE_WRITE, PMC_STATE_ACPI_READ, PMC_STATE_ACPI_WRITE, PMC_STATE_ACPI_WRITE_ADDR, }; void pmc_event(struct Pmc * pmc) { static enum PmcState state = PMC_STATE_DEFAULT; static uint8_t state_data = 0; uint8_t sts = pmc_status(pmc); // Read command/data if available if (sts & PMC_STS_IBF) { uint8_t data = pmc_read(pmc); if (sts & PMC_STS_CMD) { state = PMC_STATE_DEFAULT; switch (data) { case 0x80: state = PMC_STATE_ACPI_READ; break; case 0x81: state = PMC_STATE_ACPI_WRITE; break; case 0xEC: for (;;) { // Attempt to trigger watchdog reset ETWCFG |= (1 << 5); EWDKEYR = 0; } break; } } else { switch (state) { case PMC_STATE_ACPI_READ: state = PMC_STATE_WRITE; state_data = acpi_read(data); break; case PMC_STATE_ACPI_WRITE: state = PMC_STATE_ACPI_WRITE_ADDR; state_data = data; break; case PMC_STATE_ACPI_WRITE_ADDR: state = PMC_STATE_DEFAULT; acpi_write(state_data, data); break; default: state = PMC_STATE_DEFAULT; break; } } } // Write data if possible if (!(sts & PMC_STS_OBF)) { switch (state) { case PMC_STATE_WRITE: state = PMC_STATE_DEFAULT; pmc_write(pmc, state_data); break; } } } // Main program while running in scratch ROM void main(void) { for (;;) { pmc_event(&PMC_3); } }