summaryrefslogtreecommitdiffstats
path: root/tmk_core/protocol/arm_atsam/d51_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/protocol/arm_atsam/d51_util.c')
-rw-r--r--tmk_core/protocol/arm_atsam/d51_util.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/tmk_core/protocol/arm_atsam/d51_util.c b/tmk_core/protocol/arm_atsam/d51_util.c
new file mode 100644
index 000000000..ea4225857
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/d51_util.c
@@ -0,0 +1,227 @@
+#include "d51_util.h"
+
+static volatile uint32_t w;
+
+//Display unsigned 32-bit number by port toggling DBG_1 (to view on a scope)
+//Read as follows: 1230 = | | | | | | || (note zero is fast double toggle)
+#define DBG_PAUSE 5
+void dbg_print(uint32_t x)
+{
+ int8_t t;
+ uint32_t n;
+ uint32_t p, p2;
+
+ if (x < 10) t = 0;
+ else if (x < 100) t = 1;
+ else if (x < 1000) t = 2;
+ else if (x < 10000) t = 3;
+ else if (x < 100000) t = 4;
+ else if (x < 1000000) t = 5;
+ else if (x < 10000000) t = 6;
+ else if (x < 100000000) t = 7;
+ else if (x < 1000000000) t = 8;
+ else t = 9;
+
+ while (t >= 0)
+ {
+ p2 = t;
+ p = 1;
+ while (p2--) p *= 10;
+ n = x / p;
+ x -= n * p;
+ if (!n)
+ {
+ DBG_1_ON;
+ DBG_1_OFF;
+ DBG_1_ON;
+ DBG_1_OFF;
+ n--;
+ }
+ else
+ {
+ while (n > 0)
+ {
+ DBG_1_ON;
+ DBG_1_OFF;
+ n--;
+ }
+ }
+
+ t--;
+ }
+
+ for (w = DBG_PAUSE; w; w--); //Long pause after number is complete
+}
+
+//Display unsigned 32-bit number through debug led
+//Read as follows: 1230 = [*] [* *] [* * *] [**] (note zero is fast double flash)
+#define DLED_ONTIME 1000000
+#define DLED_PAUSE 1500000
+void dled_print(uint32_t x, uint8_t long_pause)
+{
+ int8_t t;
+ uint32_t n;
+ uint32_t p, p2;
+
+ if (x < 10) t = 0;
+ else if (x < 100) t = 1;
+ else if (x < 1000) t = 2;
+ else if (x < 10000) t = 3;
+ else if (x < 100000) t = 4;
+ else if (x < 1000000) t = 5;
+ else if (x < 10000000) t = 6;
+ else if (x < 100000000) t = 7;
+ else if (x < 1000000000) t = 8;
+ else t = 9;
+
+ while (t >= 0)
+ {
+ p2 = t;
+ p = 1;
+ while (p2--) p *= 10;
+ n = x / p;
+ x -= n * p;
+ if (!n)
+ {
+ DBG_LED_ON;
+ for (w = DLED_ONTIME / 4; w; w--);
+ DBG_LED_OFF;
+ for (w = DLED_ONTIME / 4; w; w--);
+ DBG_LED_ON;
+ for (w = DLED_ONTIME / 4; w; w--);
+ DBG_LED_OFF;
+ for (w = DLED_ONTIME / 4; w; w--);
+ n--;
+ }
+ else
+ {
+ while (n > 0)
+ {
+ DBG_LED_ON;
+ for (w = DLED_ONTIME; w; w--);
+ DBG_LED_OFF;
+ for (w = DLED_ONTIME / 2; w; w--);
+ n--;
+ }
+ }
+
+ for (w = DLED_PAUSE; w; w--);
+ t--;
+ }
+
+ if (long_pause)
+ {
+ for (w = DLED_PAUSE * 4; w; w--);
+ }
+}
+
+#ifdef DEBUG_BOOT_TRACING_ENABLE
+
+volatile uint32_t debug_code;
+
+//These macros are for compile time substitution
+#define DEBUG_BOOT_TRACING_EXTINTn (DEBUG_BOOT_TRACING_PIN % _U_(0x10))
+#define DEBUG_BOOT_TRACING_EXTINTb (_U_(0x1) << DEBUG_BOOT_TRACING_EXTINTn)
+#define DEBUG_BOOT_TRACING_CONFIG_INDn (DEBUG_BOOT_TRACING_EXTINTn / _U_(0x8))
+#define DEBUG_BOOT_TRACING_CONFIG_SENSEn (DEBUG_BOOT_TRACING_EXTINTn % _U_(0x8))
+#define DEBUG_BOOT_TRACING_CONFIG_SENSEb (DEBUG_BOOT_TRACING_CONFIG_SENSEn * _U_(0x4))
+#define DEBUG_BOOT_TRACING_IRQn (EIC_0_IRQn + DEBUG_BOOT_TRACING_EXTINTn)
+
+//These macros perform PORT+PIN definition translation to IRQn in the preprocessor
+#define PORTPIN_TO_IRQn_EXPAND(def) def
+#define PORTPIN_TO_IRQn_DEF(def) PORTPIN_TO_IRQn_EXPAND(def)
+#if DEBUG_BOOT_TRACING_PIN < 10
+#define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_ ## port ## 0 ## pin ## A_EIC_EXTINT_NUM)
+#else
+#define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_ ## port ## pin ## A_EIC_EXTINT_NUM)
+#endif
+#define PORTPIN_TO_IRQn(port, pin) PORTPIN_TO_IRQn_TODEF(port, pin)
+
+//These macros perform function name output in the preprocessor
+#define DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq) void EIC_ ## irq ## _Handler(void)
+#define DEBUG_BOOT_TRACING_HANDLER(irq) DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq)
+
+//To generate the function name of the IRQ handler catching boot tracing,
+// certain macros must be undefined, so save their current values to macro stack
+#pragma push_macro("PA")
+#pragma push_macro("PB")
+#pragma push_macro("_L_")
+
+//Undefine / redefine pushed macros
+#undef PA
+#undef PB
+#undef _L_
+#define _L_(x) x
+
+//Perform the work and output
+//Ex: PORT PB, PIN 31 = void EIC_15_Handler(void)
+DEBUG_BOOT_TRACING_HANDLER(PORTPIN_TO_IRQn(DEBUG_BOOT_TRACING_PORT, DEBUG_BOOT_TRACING_PIN))
+
+//Restore macros
+#pragma pop_macro("PA")
+#pragma pop_macro("PB")
+#pragma pop_macro("_L_")
+{
+ //This is only for non-functional keyboard troubleshooting and should be disabled after boot
+ //Intention is to lock up the keyboard here with repeating debug led code
+ while (1)
+ {
+ dled_print(debug_code, 1);
+ }
+}
+
+void debug_code_init(void)
+{
+ DBGC(DC_UNSET);
+
+ //Configure Ports for EIC
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Input
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTSET.reg = 1 << DEBUG_BOOT_TRACING_PIN; //High
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 1; //Input Enable
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 1; //Pull Enable
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 1; //Mux Enable
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; //Mux A
+
+ //Enable CLK_EIC_APB
+ MCLK->APBAMASK.bit.EIC_ = 1;
+
+ //Configure EIC
+ EIC->CTRLA.bit.SWRST = 1;
+ while (EIC->SYNCBUSY.bit.SWRST) {}
+ EIC->ASYNCH.reg = DEBUG_BOOT_TRACING_EXTINTb;
+ EIC->INTENSET.reg = DEBUG_BOOT_TRACING_EXTINTb;
+ EIC->CONFIG[DEBUG_BOOT_TRACING_CONFIG_INDn].reg |= (EIC_CONFIG_SENSE0_FALL_Val << DEBUG_BOOT_TRACING_CONFIG_SENSEb);
+ EIC->CTRLA.bit.ENABLE = 1;
+ while (EIC->SYNCBUSY.bit.ENABLE) {}
+
+ //Enable EIC IRQ
+ NVIC_EnableIRQ(DEBUG_BOOT_TRACING_IRQn);
+}
+
+void debug_code_disable(void)
+{
+ //Disable EIC IRQ
+ NVIC_DisableIRQ(DEBUG_BOOT_TRACING_IRQn);
+
+ //Disable EIC
+ EIC->CTRLA.bit.ENABLE = 0;
+ while (EIC->SYNCBUSY.bit.ENABLE) {}
+
+ //Default port configuration
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Input
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Low
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 0; //Input Disable
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 0; //Pull Disable
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 0; //Mux Disable
+ PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; //Mux A
+
+ //Disable CLK_EIC_APB
+ MCLK->APBAMASK.bit.EIC_ = 0;
+}
+
+#else
+
+void debug_code_init(void) {}
+void debug_code_disable(void) {}
+
+#endif //DEBUG_BOOT_TRACING_ENABLE