29#include "freertos/FreeRTOS.h"
32#include "driver/rtc_io.h"
33#include "soc/sens_reg.h"
34#if __has_include("soc/rtc_io_periph.h")
35 #include "soc/rtc_io_periph.h"
41#include "ulp_macro_ex.h"
47#pragma GCC optimize ("O2")
48#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
59#define OPCODE_PLACEHOLDER 12
61#define SUB_OPCODE_DAT_ENABLE_OUTPUT 0
62#define SUB_OPCODE_DAT_ENABLE_INPUT 1
63#define SUB_OPCODE_CLK_ENABLE_OUTPUT 2
64#define SUB_OPCODE_CLK_ENABLE_INPUT 3
65#define SUB_OPCODE_READ_CLK 4
66#define SUB_OPCODE_READ_DAT 5
67#define SUB_OPCODE_WRITE_CLK 6
68#define SUB_OPCODE_WRITE_DAT 7
74#define DAT_ENABLE_OUTPUT(ps2port, value) { .macro = { \
77 .sub_opcode = SUB_OPCODE_DAT_ENABLE_OUTPUT, \
78 .opcode = OPCODE_PLACEHOLDER } }
80#define DAT_ENABLE_INPUT(ps2port, value) { .macro = { \
83 .sub_opcode = SUB_OPCODE_DAT_ENABLE_INPUT, \
84 .opcode = OPCODE_PLACEHOLDER } }
86#define CLK_ENABLE_OUTPUT(ps2port, value) { .macro = { \
89 .sub_opcode = SUB_OPCODE_CLK_ENABLE_OUTPUT, \
90 .opcode = OPCODE_PLACEHOLDER } }
92#define CLK_ENABLE_INPUT(ps2port, value) { .macro = { \
95 .sub_opcode = SUB_OPCODE_CLK_ENABLE_INPUT, \
96 .opcode = OPCODE_PLACEHOLDER } }
99#define READ_CLK(ps2port) { .macro = { \
102 .sub_opcode = SUB_OPCODE_READ_CLK, \
103 .opcode = OPCODE_PLACEHOLDER } }
106#define READ_DAT(ps2port) { .macro = { \
109 .sub_opcode = SUB_OPCODE_READ_DAT, \
110 .opcode = OPCODE_PLACEHOLDER } }
113#define WRITE_CLK(ps2port, value) { .macro = { \
116 .sub_opcode = SUB_OPCODE_WRITE_CLK, \
117 .opcode = OPCODE_PLACEHOLDER } }
120#define WRITE_DAT(ps2port, value) { .macro = { \
123 .sub_opcode = SUB_OPCODE_WRITE_DAT, \
124 .opcode = OPCODE_PLACEHOLDER } }
131#define CONFIGURE_DAT_INPUT(ps2port) \
132 DAT_ENABLE_OUTPUT(ps2port, 0), \
133 DAT_ENABLE_INPUT(ps2port, 1)
136#define CONFIGURE_DAT_OUTPUT(ps2port) \
137 DAT_ENABLE_OUTPUT(ps2port, 1), \
138 DAT_ENABLE_INPUT(ps2port, 0)
141#define CONFIGURE_CLK_INPUT(ps2port) \
142 CLK_ENABLE_OUTPUT(ps2port, 0), \
143 CLK_ENABLE_INPUT(ps2port, 1)
146#define CONFIGURE_CLK_OUTPUT(ps2port) \
147 CLK_ENABLE_OUTPUT(ps2port, 1), \
148 CLK_ENABLE_INPUT(ps2port, 0)
152#define WRITE_DAT_R0(ps2port) \
154 WRITE_DAT(ps2port, 1), \
156 WRITE_DAT(ps2port, 0)
160#define MEM_WRITEI(addr, value) \
167#define MEM_INDWRITEI(addr, value) \
175#define MEM_WRITER(addr, reg) \
181#define MEM_INDWRITER(addr, reg) \
187#define MEM_READR(reg, addr) \
192#define MEM_INDREADR(reg, addr) \
199#define MEM_INC(addr) \
207#define MEM_BL(label, addr, value) \
214#define MEM_BGE(label, addr, value) \
220#define M_LONG_BGE(label, value) \
225#define M_LONG_BL(label, value) \
230#define M_LONG_BE(label, value) \
232 I_BGE(2, value + 1), \
236#define M_LONG_BNE(label, value) \
239 I_BL(2, value + 1), \
242#define M_LONG_STAGEBLE(label_num, imm_value) \
243 I_STAGEBLE(2, imm_value), \
244 I_STAGEBGE(2, imm_value), \
247#define M_LONG_STAGEBL(label_num, imm_value) \
248 I_STAGEBGE(2, imm_value), \
251#define M_LONG_STAGEBGE(label_num, imm_value) \
252 I_STAGEBL(2, imm_value), \
256#define M_DELAY_US(us) I_DELAY(us * 8)
265#define RTCMEM_PROG_START 0x000
266#define RTCMEM_VARS_START 0x200
269#define RTCMEM_PORT0_TX (RTCMEM_VARS_START + 0)
270#define RTCMEM_PORT1_TX (RTCMEM_VARS_START + 1)
271#define RTCMEM_PORT0_RX_ENABLE (RTCMEM_VARS_START + 2)
272#define RTCMEM_PORT1_RX_ENABLE (RTCMEM_VARS_START + 3)
273#define RTCMEM_PORT0_RX_DISABLE (RTCMEM_VARS_START + 4)
274#define RTCMEM_PORT1_RX_DISABLE (RTCMEM_VARS_START + 5)
276#define RTCMEM_PORT0_DATAOUT (RTCMEM_VARS_START + 6)
277#define RTCMEM_PORT1_DATAOUT (RTCMEM_VARS_START + 7)
280#define RTCMEM_PORT0_RX (RTCMEM_VARS_START + 8)
281#define RTCMEM_PORT1_RX (RTCMEM_VARS_START + 9)
282#define RTCMEM_PORT0_RX_CLK_TIMEOUT (RTCMEM_VARS_START + 10)
283#define RTCMEM_PORT1_RX_CLK_TIMEOUT (RTCMEM_VARS_START + 11)
285#define RTCMEM_PORT0_DATAIN (RTCMEM_VARS_START + 12)
286#define RTCMEM_PORT1_DATAIN (RTCMEM_VARS_START + 13)
289#define RTCMEM_PORT0_RX_ENABLED (RTCMEM_VARS_START + 14)
290#define RTCMEM_PORT1_RX_ENABLED (RTCMEM_VARS_START + 15)
292#define RTCMEM_LASTVAR (RTCMEM_VARS_START + 15)
296#define CLK_RX_TIMEOUT_VAL 100
299#define CLK_TX_TIMEOUT_VAL 1200
302#define WAKE_THRESHOLD 3000
306#if RTCMEM_LASTVAR >= 0x800
307#error "ULP program too big"
313#define LABEL_WAIT_COMMAND 0
316#define LABEL_RX_NEXT 2
318#define LABEL_PORT0_ENABLE_RX 3
319#define LABEL_PORT0_STOP_RX 4
320#define LABEL_PORT0_TX 5
321#define LABEL_PORT0_TX_NEXT_BIT 6
322#define LABEL_PORT0_TX_WAIT_CLK_HIGH 7
323#define LABEL_PORT0_TX_EXIT 8
324#define LABEL_PORT0_RX_WAIT_LOOP 9
325#define LABEL_PORT0_RX_CLK_IS_HIGH 10
326#define LABEL_PORT0_RX_CLK_IS_LOW 11
327#define LABEL_PORT0_RX_CLK_TIMEOUT 12
328#define LABEL_PORT0_RX_CHECK_CLK 13
330#define LABEL_PORT1_ENABLE_RX 14
331#define LABEL_PORT1_STOP_RX 15
332#define LABEL_PORT1_TX 16
333#define LABEL_PORT1_TX_NEXT_BIT 17
334#define LABEL_PORT1_TX_WAIT_CLK_HIGH 18
335#define LABEL_PORT1_TX_EXIT 19
336#define LABEL_PORT1_RX_WAIT_LOOP 20
337#define LABEL_PORT1_RX_CLK_IS_HIGH 21
338#define LABEL_PORT1_RX_CLK_IS_LOW 22
339#define LABEL_PORT1_RX_CLK_TIMEOUT 23
340#define LABEL_PORT1_RX_CHECK_CLK 24
348#define TEMP_PORT0_DISABLE() \
349 I_LD(R0, R3, RTCMEM_PORT0_RX_ENABLED), \
351 CONFIGURE_CLK_OUTPUT(PS2_PORT0), \
352 WRITE_CLK(PS2_PORT0, 0)
357#define TEMP_PORT0_ENABLE() \
358 I_LD(R0, R3, RTCMEM_PORT0_RX_ENABLED), \
360 CONFIGURE_CLK_INPUT(PS2_PORT0)
365#define TEMP_PORT1_DISABLE() \
366 I_LD(R0, R3, RTCMEM_PORT1_RX_ENABLED), \
368 CONFIGURE_CLK_OUTPUT(PS2_PORT1), \
369 WRITE_CLK(PS2_PORT1, 0)
374#define TEMP_PORT1_ENABLE() \
375 I_LD(R0, R3, RTCMEM_PORT1_RX_ENABLED), \
377 CONFIGURE_CLK_INPUT(PS2_PORT1)
381#define PERM_PORT0_DISABLE() \
383 I_ST(R0, R3, RTCMEM_PORT0_RX_ENABLED), \
384 CONFIGURE_CLK_OUTPUT(PS2_PORT0), \
385 WRITE_CLK(PS2_PORT0, 0)
389#define PERM_PORT1_DISABLE() \
391 I_ST(R0, R3, RTCMEM_PORT1_RX_ENABLED), \
392 CONFIGURE_CLK_OUTPUT(PS2_PORT1), \
393 WRITE_CLK(PS2_PORT1, 0)
421const ulp_insn_t ULP_code[] = {
434M_LABEL(LABEL_WAIT_COMMAND),
437 I_LD(R0, R3, RTCMEM_PORT0_TX),
438 M_BGE(LABEL_PORT0_TX, 1),
441 I_LD(R0, R3, RTCMEM_PORT0_RX_ENABLE),
442 M_BGE(LABEL_PORT0_ENABLE_RX, 1),
445 I_LD(R0, R3, RTCMEM_PORT0_RX_DISABLE),
446 M_BGE(LABEL_PORT0_STOP_RX, 1),
449 I_LD(R0, R3, RTCMEM_PORT1_TX),
450 M_BGE(LABEL_PORT1_TX, 1),
453 I_LD(R0, R3, RTCMEM_PORT1_RX_ENABLE),
454 M_BGE(LABEL_PORT1_ENABLE_RX, 1),
457 I_LD(R0, R3, RTCMEM_PORT1_RX_DISABLE),
458 M_BGE(LABEL_PORT1_STOP_RX, 1),
467M_LABEL(LABEL_PORT0_ENABLE_RX),
471 I_ST(R0, R3, RTCMEM_PORT0_RX_ENABLED),
474 CONFIGURE_CLK_INPUT(PS2_PORT0),
475 CONFIGURE_DAT_INPUT(PS2_PORT0),
479 I_ST(R0, R3, RTCMEM_PORT0_RX_ENABLE),
487M_LABEL(LABEL_PORT1_ENABLE_RX),
491 I_ST(R0, R3, RTCMEM_PORT1_RX_ENABLED),
494 CONFIGURE_CLK_INPUT(PS2_PORT1),
495 CONFIGURE_DAT_INPUT(PS2_PORT1),
499 I_ST(R0, R3, RTCMEM_PORT1_RX_ENABLE),
507M_LABEL(LABEL_PORT0_STOP_RX),
509 PERM_PORT0_DISABLE(),
513 I_ST(R0, R3, RTCMEM_PORT0_RX_DISABLE),
521M_LABEL(LABEL_PORT1_STOP_RX),
523 PERM_PORT1_DISABLE(),
527 I_ST(R0, R3, RTCMEM_PORT1_RX_DISABLE),
536M_LABEL(LABEL_PORT0_TX),
541 I_LD(R2, R3, RTCMEM_PORT0_DATAOUT),
547 TEMP_PORT1_DISABLE(),
550 CONFIGURE_CLK_OUTPUT(PS2_PORT0),
551 WRITE_CLK(PS2_PORT0, 0),
553 CONFIGURE_DAT_OUTPUT(PS2_PORT0),
554 WRITE_DAT(PS2_PORT0, 0),
557 CONFIGURE_CLK_INPUT(PS2_PORT0),
559M_LABEL(LABEL_PORT0_TX_NEXT_BIT),
566 M_BGE(LABEL_PORT0_TX_EXIT, CLK_TX_TIMEOUT_VAL),
572 M_BGE(LABEL_PORT0_TX_NEXT_BIT, 1),
578 M_STAGEBGE(LABEL_PORT0_TX_WAIT_CLK_HIGH, 10),
582 WRITE_DAT_R0(PS2_PORT0),
584M_LABEL(LABEL_PORT0_TX_WAIT_CLK_HIGH),
592 M_BL(LABEL_PORT0_TX_WAIT_CLK_HIGH, 1),
601 M_STAGEBL(LABEL_PORT0_TX_NEXT_BIT, 11),
603M_LABEL(LABEL_PORT0_TX_EXIT),
609 CONFIGURE_DAT_INPUT(PS2_PORT0),
611 I_ST(R0, R3, RTCMEM_PORT0_RX_ENABLED),
615 I_ST(R0, R3, RTCMEM_PORT0_TX),
631M_LABEL(LABEL_PORT1_TX),
636 I_LD(R2, R3, RTCMEM_PORT1_DATAOUT),
642 TEMP_PORT0_DISABLE(),
645 CONFIGURE_CLK_OUTPUT(PS2_PORT1),
646 WRITE_CLK(PS2_PORT1, 0),
648 CONFIGURE_DAT_OUTPUT(PS2_PORT1),
649 WRITE_DAT(PS2_PORT1, 0),
652 CONFIGURE_CLK_INPUT(PS2_PORT1),
654M_LABEL(LABEL_PORT1_TX_NEXT_BIT),
661 M_BGE(LABEL_PORT1_TX_EXIT, CLK_TX_TIMEOUT_VAL),
667 M_BGE(LABEL_PORT1_TX_NEXT_BIT, 1),
673 M_STAGEBGE(LABEL_PORT1_TX_WAIT_CLK_HIGH, 10),
677 WRITE_DAT_R0(PS2_PORT1),
679M_LABEL(LABEL_PORT1_TX_WAIT_CLK_HIGH),
687 M_BL(LABEL_PORT1_TX_WAIT_CLK_HIGH, 1),
696 M_STAGEBL(LABEL_PORT1_TX_NEXT_BIT, 11),
698M_LABEL(LABEL_PORT1_TX_EXIT),
704 CONFIGURE_DAT_INPUT(PS2_PORT1),
706 I_ST(R0, R3, RTCMEM_PORT1_RX_ENABLED),
710 I_ST(R0, R3, RTCMEM_PORT1_TX),
725M_LABEL(LABEL_PORT0_RX_CLK_TIMEOUT),
731 PERM_PORT0_DISABLE(),
738 I_ST(R0, R3, RTCMEM_PORT0_RX_CLK_TIMEOUT),
751M_LABEL(LABEL_PORT1_RX_CLK_TIMEOUT),
757 PERM_PORT1_DISABLE(),
764 I_ST(R0, R3, RTCMEM_PORT1_RX_CLK_TIMEOUT),
782 I_LD(R0, R3, RTCMEM_PORT0_RX_ENABLED),
783 M_BGE(LABEL_PORT0_RX_CHECK_CLK, 1),
788 M_BL(LABEL_RX_NEXT, WAKE_THRESHOLD),
793M_LABEL(LABEL_PORT0_RX_CHECK_CLK),
799 M_BGE(LABEL_RX_NEXT, 1),
805 I_ST(R0, R3, RTCMEM_PORT0_DATAIN),
810 TEMP_PORT1_DISABLE(),
813 M_BX(LABEL_PORT0_RX_CLK_IS_LOW),
815M_LABEL(LABEL_PORT0_RX_WAIT_LOOP),
820 M_BGE(LABEL_PORT0_RX_CLK_TIMEOUT, CLK_RX_TIMEOUT_VAL),
827 M_BXZ(LABEL_PORT0_RX_WAIT_LOOP),
836 M_BGE(LABEL_PORT0_RX_CLK_IS_HIGH, 1),
838M_LABEL(LABEL_PORT0_RX_CLK_IS_LOW),
845 I_LD(R1, R3, RTCMEM_PORT0_DATAIN),
848 I_ST(R1, R3, RTCMEM_PORT0_DATAIN),
851 M_BX(LABEL_PORT0_RX_WAIT_LOOP),
853M_LABEL(LABEL_PORT0_RX_CLK_IS_HIGH),
859 M_STAGEBL(LABEL_PORT0_RX_WAIT_LOOP, 11),
862 PERM_PORT0_DISABLE(),
866 I_ST(R0, R3, RTCMEM_PORT0_RX),
884M_LABEL(LABEL_RX_NEXT),
887 I_LD(R0, R3, RTCMEM_PORT1_RX_ENABLED),
888 M_BGE(LABEL_PORT1_RX_CHECK_CLK, 1),
893 M_LONG_BL(LABEL_WAIT_COMMAND, WAKE_THRESHOLD),
896 M_BX(LABEL_WAIT_COMMAND),
898M_LABEL(LABEL_PORT1_RX_CHECK_CLK),
904 M_LONG_BGE(LABEL_WAIT_COMMAND, 1),
910 I_ST(R0, R3, RTCMEM_PORT1_DATAIN),
915 TEMP_PORT0_DISABLE(),
918 M_BX(LABEL_PORT1_RX_CLK_IS_LOW),
920M_LABEL(LABEL_PORT1_RX_WAIT_LOOP),
925 M_BGE(LABEL_PORT1_RX_CLK_TIMEOUT, CLK_RX_TIMEOUT_VAL),
932 M_BXZ(LABEL_PORT1_RX_WAIT_LOOP),
941 M_BGE(LABEL_PORT1_RX_CLK_IS_HIGH, 1),
943M_LABEL(LABEL_PORT1_RX_CLK_IS_LOW),
950 I_LD(R1, R3, RTCMEM_PORT1_DATAIN),
953 I_ST(R1, R3, RTCMEM_PORT1_DATAIN),
956 M_BX(LABEL_PORT1_RX_WAIT_LOOP),
958M_LABEL(LABEL_PORT1_RX_CLK_IS_HIGH),
964 M_STAGEBL(LABEL_PORT1_RX_WAIT_LOOP, 11),
967 PERM_PORT1_DISABLE(),
971 I_ST(R0, R3, RTCMEM_PORT1_RX),
984 M_BX(LABEL_WAIT_COMMAND),
995static void replace_placeholders(uint32_t prg_start,
int size,
bool port0Enabled, gpio_num_t port0_clkGPIO, gpio_num_t port0_datGPIO,
bool port1Enabled, gpio_num_t port1_clkGPIO, gpio_num_t port1_datGPIO)
997 uint32_t CLK_rtc_gpio_num[2], CLK_rtc_gpio_reg[2], CLK_rtc_gpio_ie_s[2];
998 uint32_t DAT_rtc_gpio_num[2], DAT_rtc_gpio_reg[2], DAT_rtc_gpio_ie_s[2];
1001 #if FABGL_ESP_IDF_VERSION <= FABGL_ESP_IDF_VERSION_VAL(3, 3, 5)
1002 CLK_rtc_gpio_num[0] = (uint32_t) rtc_gpio_desc[port0_clkGPIO].rtc_num;
1003 CLK_rtc_gpio_reg[0] = rtc_gpio_desc[port0_clkGPIO].reg;
1004 CLK_rtc_gpio_ie_s[0] = (uint32_t) ffs(rtc_gpio_desc[port0_clkGPIO].ie) - 1;
1005 DAT_rtc_gpio_num[0] = (uint32_t) rtc_gpio_desc[port0_datGPIO].rtc_num;
1006 DAT_rtc_gpio_reg[0] = rtc_gpio_desc[port0_datGPIO].reg;
1007 DAT_rtc_gpio_ie_s[0] = (uint32_t) ffs(rtc_gpio_desc[port0_datGPIO].ie) - 1;
1009 int port0_clkIO = rtc_io_number_get(port0_clkGPIO);
1010 CLK_rtc_gpio_num[0] = port0_clkIO;
1011 CLK_rtc_gpio_reg[0] = rtc_io_desc[port0_clkIO].reg;
1012 CLK_rtc_gpio_ie_s[0] = (uint32_t) ffs(rtc_io_desc[port0_clkIO].ie) - 1;
1013 int port0_datIO = rtc_io_number_get(port0_datGPIO);
1014 DAT_rtc_gpio_num[0] = port0_datIO;
1015 DAT_rtc_gpio_reg[0] = rtc_io_desc[port0_datIO].reg;
1016 DAT_rtc_gpio_ie_s[0] = (uint32_t) ffs(rtc_io_desc[port0_datIO].ie) - 1;
1021 #if FABGL_ESP_IDF_VERSION <= FABGL_ESP_IDF_VERSION_VAL(3, 3, 5)
1022 CLK_rtc_gpio_num[1] = (uint32_t) rtc_gpio_desc[port1_clkGPIO].rtc_num;
1023 CLK_rtc_gpio_reg[1] = rtc_gpio_desc[port1_clkGPIO].reg;
1024 CLK_rtc_gpio_ie_s[1] = (uint32_t) ffs(rtc_gpio_desc[port1_clkGPIO].ie) - 1;
1025 DAT_rtc_gpio_num[1] = (uint32_t) rtc_gpio_desc[port1_datGPIO].rtc_num;
1026 DAT_rtc_gpio_reg[1] = rtc_gpio_desc[port1_datGPIO].reg;
1027 DAT_rtc_gpio_ie_s[1] = (uint32_t) ffs(rtc_gpio_desc[port1_datGPIO].ie) - 1;
1029 int port1_clkIO = rtc_io_number_get(port1_clkGPIO);
1030 CLK_rtc_gpio_num[1] = port1_clkIO;
1031 CLK_rtc_gpio_reg[1] = rtc_io_desc[port1_clkIO].reg;
1032 CLK_rtc_gpio_ie_s[1] = (uint32_t) ffs(rtc_io_desc[port1_clkIO].ie) - 1;
1033 int port1_datIO = rtc_io_number_get(port1_datGPIO);
1034 DAT_rtc_gpio_num[1] = port1_datIO;
1035 DAT_rtc_gpio_reg[1] = rtc_io_desc[port1_datIO].reg;
1036 DAT_rtc_gpio_ie_s[1] = (uint32_t) ffs(rtc_io_desc[port1_datIO].ie) - 1;
1040 for (uint32_t i = 0; i < size; ++i) {
1041 ulp_insn_t * ins = (ulp_insn_t *) RTC_SLOW_MEM + i;
1042 if (ins->macro.opcode == OPCODE_PLACEHOLDER) {
1043 int ps2port = ins->macro.unused;
1044 if ((port0Enabled && ps2port == 0) || (port1Enabled && ps2port == 1)) {
1045 ins->macro.unused = 0;
1046 switch (ins->macro.sub_opcode) {
1047 case SUB_OPCODE_DAT_ENABLE_OUTPUT:
1048 if (ins->macro.label)
1049 *ins = (ulp_insn_t) I_WR_REG_BIT(RTC_GPIO_ENABLE_W1TS_REG, DAT_rtc_gpio_num[ps2port] + RTC_GPIO_ENABLE_W1TS_S, 1);
1051 *ins = (ulp_insn_t) I_WR_REG_BIT(RTC_GPIO_ENABLE_W1TC_REG, DAT_rtc_gpio_num[ps2port] + RTC_GPIO_ENABLE_W1TC_S, 1);
1053 case SUB_OPCODE_DAT_ENABLE_INPUT:
1054 *ins = (ulp_insn_t) I_WR_REG_BIT(DAT_rtc_gpio_reg[ps2port], DAT_rtc_gpio_ie_s[ps2port], ins->macro.label);
1056 case SUB_OPCODE_CLK_ENABLE_OUTPUT:
1057 if (ins->macro.label)
1058 *ins = (ulp_insn_t) I_WR_REG_BIT(RTC_GPIO_ENABLE_W1TS_REG, CLK_rtc_gpio_num[ps2port] + RTC_GPIO_ENABLE_W1TS_S, 1);
1060 *ins = (ulp_insn_t) I_WR_REG_BIT(RTC_GPIO_ENABLE_W1TC_REG, CLK_rtc_gpio_num[ps2port] + RTC_GPIO_ENABLE_W1TC_S, 1);
1062 case SUB_OPCODE_CLK_ENABLE_INPUT:
1063 *ins = (ulp_insn_t) I_WR_REG_BIT(CLK_rtc_gpio_reg[ps2port], CLK_rtc_gpio_ie_s[ps2port], ins->macro.label);
1065 case SUB_OPCODE_READ_CLK:
1066 *ins = (ulp_insn_t) I_RD_REG(RTC_GPIO_IN_REG, CLK_rtc_gpio_num[ps2port] + RTC_GPIO_IN_NEXT_S, CLK_rtc_gpio_num[ps2port] + RTC_GPIO_IN_NEXT_S);
1068 case SUB_OPCODE_READ_DAT:
1069 *ins = (ulp_insn_t) I_RD_REG(RTC_GPIO_IN_REG, DAT_rtc_gpio_num[ps2port] + RTC_GPIO_IN_NEXT_S, DAT_rtc_gpio_num[ps2port] + RTC_GPIO_IN_NEXT_S);
1071 case SUB_OPCODE_WRITE_CLK:
1072 *ins = (ulp_insn_t) I_WR_REG_BIT(RTC_GPIO_OUT_REG, CLK_rtc_gpio_num[ps2port] + RTC_GPIO_IN_NEXT_S, ins->macro.label);
1074 case SUB_OPCODE_WRITE_DAT:
1075 *ins = (ulp_insn_t) I_WR_REG_BIT(RTC_GPIO_OUT_REG, DAT_rtc_gpio_num[ps2port] + RTC_GPIO_IN_NEXT_S, ins->macro.label);
1084PS2Controller * PS2Controller::s_instance =
nullptr;
1085Keyboard * PS2Controller::s_keyboard =
nullptr;
1086Mouse * PS2Controller::s_mouse =
nullptr;
1087bool PS2Controller::s_keyboardAllocated =
false;
1088bool PS2Controller::s_mouseAllocated =
false;
1089bool PS2Controller::s_portEnabled[2];
1090intr_handle_t PS2Controller::s_ULPWakeISRHandle;
1091bool PS2Controller::s_parityError[2];
1092bool PS2Controller::s_syncError[2];
1093bool PS2Controller::s_CLKTimeOutError[2];
1094QueueHandle_t PS2Controller::s_dataIn[2];
1095SemaphoreHandle_t PS2Controller::s_portLock[2];
1096bool PS2Controller::s_initDone =
false;
1099PS2Controller::PS2Controller()
1106PS2Controller::~PS2Controller()
1109 if (
this == s_instance)
1110 s_instance =
nullptr;
1115void PS2Controller::begin(gpio_num_t port0_clkGPIO, gpio_num_t port0_datGPIO, gpio_num_t port1_clkGPIO, gpio_num_t port1_datGPIO)
1120 s_portEnabled[0] = (port0_clkGPIO != GPIO_UNUSED && port0_datGPIO != GPIO_UNUSED);
1121 s_portEnabled[1] = (port1_clkGPIO != GPIO_UNUSED && port1_datGPIO != GPIO_UNUSED);
1123 if (s_portEnabled[0]) {
1124 if (!rtc_gpio_is_valid_gpio(port0_clkGPIO) || !rtc_gpio_is_valid_gpio(port0_datGPIO)) {
1125 ESP_LOGE(
"FabGL",
"Invalid PS/2 Port 0 pins");
1126 s_portEnabled[0] =
false;
1128 rtc_gpio_init(port0_clkGPIO);
1129 rtc_gpio_init(port0_datGPIO);
1133 if (s_portEnabled[1]) {
1134 if (!rtc_gpio_is_valid_gpio(port1_clkGPIO) || !rtc_gpio_is_valid_gpio(port1_datGPIO)) {
1135 ESP_LOGE(
"FabGL",
"Invalid PS/2 Port 1 pins");
1136 s_portEnabled[1] =
false;
1138 rtc_gpio_init(port1_clkGPIO);
1139 rtc_gpio_init(port1_datGPIO);
1144 for (
int i = RTCMEM_PROG_START; i < RTCMEM_LASTVAR; ++i)
1145 RTC_SLOW_MEM[i] = 0x0000;
1148 size_t size =
sizeof(ULP_code) /
sizeof(ulp_insn_t);
1149 ulp_process_macros_and_load_ex(RTCMEM_PROG_START, ULP_code, &size);
1150 replace_placeholders(RTCMEM_PROG_START, size, s_portEnabled[0], port0_clkGPIO, port0_datGPIO, s_portEnabled[1], port1_clkGPIO, port1_datGPIO);
1152 assert(size < RTCMEM_VARS_START &&
"ULP Program too long, increase RTCMEM_VARS_START");
1154 REG_SET_FIELD(SENS_SAR_START_FORCE_REG, SENS_PC_INIT, RTCMEM_PROG_START);
1155 SET_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_FORCE_START_TOP);
1157 for (
int p = 0; p < 2; ++p) {
1158 RTC_SLOW_MEM[RTCMEM_PORT0_TX + p] = 0;
1159 RTC_SLOW_MEM[RTCMEM_PORT0_RX_ENABLE + p] = 0;
1160 RTC_SLOW_MEM[RTCMEM_PORT0_RX_DISABLE + p] = 0;
1161 RTC_SLOW_MEM[RTCMEM_PORT0_RX + p] = 0;
1162 RTC_SLOW_MEM[RTCMEM_PORT0_RX_ENABLED + p] = 0;
1163 s_parityError[p] = s_syncError[p] =
false;
1164 s_dataIn[p] = (s_portEnabled[p] ? xQueueCreate(1,
sizeof(uint16_t)) :
nullptr);
1165 s_portLock[p] = (s_portEnabled[p] ? xSemaphoreCreateRecursiveMutex() :
nullptr);
1170 SET_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_START_TOP);
1175 esp_intr_alloc_pinnedToCore(ETS_RTC_CORE_INTR_SOURCE, ESP_INTR_FLAG_LEVEL2, ULPWakeISR,
nullptr, &s_ULPWakeISRHandle, 1);
1176 SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA);
1183 for (
int p = 0; p < 2; ++p) {
1184 RTC_SLOW_MEM[RTCMEM_PORT0_TX + p] = 0;
1185 RTC_SLOW_MEM[RTCMEM_PORT0_RX_ENABLE + p] = 0;
1186 RTC_SLOW_MEM[RTCMEM_PORT0_RX_DISABLE + p] = 0;
1187 RTC_SLOW_MEM[RTCMEM_PORT0_RX + p] = 0;
1188 RTC_SLOW_MEM[RTCMEM_PORT0_RX_ENABLED + p] = 0;
1189 s_parityError[p] = s_syncError[p] =
false;
1190 if (s_portEnabled[p]) {
1191 xQueueReset(s_dataIn[p]);
1192 xSemaphoreGiveRecursive(s_portLock[p]);
1209 begin(GPIO_NUM_33, GPIO_NUM_32, GPIO_NUM_26, GPIO_NUM_27);
1212 setMouse(
new Mouse);
1214 s_keyboardAllocated = s_mouseAllocated =
true;
1218 begin(GPIO_NUM_33, GPIO_NUM_32, GPIO_NUM_26, GPIO_NUM_27);
1219 setMouse(
new Mouse);
1223 s_keyboardAllocated = s_mouseAllocated =
true;
1228 (
new Keyboard)->
begin(GPIO_NUM_33, GPIO_NUM_32, generateVirtualKeys, createVKQueue);
1229 s_keyboardAllocated =
true;
1234 (
new Keyboard)->
begin(GPIO_NUM_26, GPIO_NUM_27, generateVirtualKeys, createVKQueue);
1235 s_keyboardAllocated =
true;
1240 (
new Mouse)->
begin(GPIO_NUM_33, GPIO_NUM_32);
1241 s_mouseAllocated =
true;
1246 (
new Mouse)->
begin(GPIO_NUM_26, GPIO_NUM_27);
1247 s_mouseAllocated =
true;
1253void PS2Controller::end()
1256 if (s_keyboardAllocated)
1258 s_keyboard =
nullptr;
1260 if (s_mouseAllocated)
1264 for (
int p = 0; p < 2; ++p)
1272 if (s_portEnabled[PS2Port])
1273 RTC_SLOW_MEM[RTCMEM_PORT0_RX_DISABLE + PS2Port] = 1;
1279 if (s_portEnabled[PS2Port]) {
1282 RTC_SLOW_MEM[RTCMEM_PORT0_RX_ENABLE + PS2Port] = 1;
1289 return uxQueueMessagesWaiting(s_dataIn[PS2Port]);
1299 if (xQueueReceive(s_dataIn[PS2Port], &w, msToTicks(timeOutMS))) {
1302 s_CLKTimeOutError[PS2Port] = (w == 0xffff);
1303 if (!s_CLKTimeOutError[PS2Port]) {
1304 uint8_t startBit = w & 1;
1305 uint8_t stopBit = (w >> 10) & 1;
1306 uint8_t parity = (w >> 9) & 1;
1307 r = (w >> 1) & 0xff;
1308 s_parityError[PS2Port] = (parity != !calcParity(r));
1309 s_syncError[PS2Port] = (startBit != 0 || stopBit != 1);
1310 if (s_parityError[PS2Port] || s_syncError[PS2Port])
1315 RTC_SLOW_MEM[RTCMEM_PORT0_RX_ENABLE + PS2Port] = 1;
1325 if (s_portEnabled[PS2Port]) {
1326 RTC_SLOW_MEM[RTCMEM_PORT0_DATAOUT + PS2Port] = 0x200 | ((!calcParity(
data) & 1) << 8) |
data;
1327 RTC_SLOW_MEM[RTCMEM_PORT0_TX + PS2Port] = 1;
1334 return s_portEnabled[PS2Port] ? xSemaphoreTakeRecursive(s_portLock[PS2Port], msToTicks(timeOutMS)) :
true;
1340 if (s_portEnabled[PS2Port])
1341 xSemaphoreGiveRecursive(s_portLock[PS2Port]);
1346void IRAM_ATTR PS2Controller::ULPWakeISR(
void * arg)
1348 uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG);
1350 if (rtc_intr & RTC_CNTL_SAR_INT_ST) {
1352 for (
int p = 0; p < 2; ++p) {
1353 if (RTC_SLOW_MEM[RTCMEM_PORT0_RX + p] & 0xffff) {
1355 uint16_t d = RTC_SLOW_MEM[RTCMEM_PORT0_DATAIN + p] & 0xffff;
1356 xQueueOverwriteFromISR(PS2Controller::s_dataIn[p], &d,
nullptr);
1357 RTC_SLOW_MEM[RTCMEM_PORT0_RX + p] = 0;
1358 }
else if (RTC_SLOW_MEM[RTCMEM_PORT0_RX_CLK_TIMEOUT + p] & 0xffff) {
1360 uint16_t d = 0xffff;
1361 xQueueOverwriteFromISR(PS2Controller::s_dataIn[p], &d,
nullptr);
1362 RTC_SLOW_MEM[RTCMEM_PORT0_RX_CLK_TIMEOUT + p] = 0;
1369 WRITE_PERI_REG(RTC_CNTL_INT_CLR_REG, rtc_intr);
void begin(gpio_num_t clkGPIO, gpio_num_t dataGPIO, bool generateVirtualKeys=true, bool createVKQueue=true)
Initializes Keyboard specifying CLOCK and DATA GPIOs.
The PS2 Keyboard controller class.
void begin(gpio_num_t clkGPIO, gpio_num_t dataGPIO)
Initializes Mouse specifying CLOCK and DATA GPIOs.
The PS2 Mouse controller class.
static Mouse * mouse()
Returns the instance of Mouse object automatically created by PS2Controller.
static void sendData(uint8_t data, int PS2Port)
Sends a command to the device.
static bool lock(int PS2Port, int timeOutMS)
Gets exclusive access to the specified PS/2 port.
static void disableRX(int PS2Port)
Disables inputs from PS/2 port driving the CLK line Low.
static Keyboard * keyboard()
Returns the instance of Keyboard object automatically created by PS2Controller.
static void unlock(int PS2Port)
Releases port from exclusive access.
static void begin(gpio_num_t port0_clkGPIO, gpio_num_t port0_datGPIO, gpio_num_t port1_clkGPIO=GPIO_UNUSED, gpio_num_t port1_datGPIO=GPIO_UNUSED)
Initializes PS2 device controller.
static int getData(int PS2Port, int timeOutMS)
Gets a scancode from the queue.
static bool dataAvailable(int PS2Port)
Determines if one byte has been received from the specified port.
static void enableRX(int PS2Port)
Enables inputs from PS/2 port releasing CLK line.
This file contains some utility classes and functions.
KbdMode
This enum defines how handle keyboard virtual keys.
PS2Preset
This enum defines what is connected to PS/2 ports.
@ KeyboardPort0_MousePort1
@ KeyboardPort1_MousePort0
This file contains fabgl::Keyboard definition.
This file contains fabgl::Mouse definition.
This file contains fabgl::PS2Controller definition.