]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/arm_atsam/d51_util.c
Bringing Massdrop keyboard hardware configuration to keyboard level (#4593)
[qmk_firmware.git] / tmk_core / protocol / arm_atsam / d51_util.c
1 #include "d51_util.h"
2
3 static volatile uint32_t w;
4     
5 //Display unsigned 32-bit number by port toggling DBG_1 (to view on a scope)
6 //Read as follows: 1230 = |    | |    | | |    ||  (note zero is fast double toggle)
7 #define DBG_PAUSE 5
8 void dbg_print(uint32_t x)
9 {
10     int8_t t;
11     uint32_t n;
12     uint32_t p, p2;
13
14     if      (x < 10) t = 0;
15     else if (x < 100) t = 1;
16     else if (x < 1000) t = 2;
17     else if (x < 10000) t = 3;
18     else if (x < 100000) t = 4;
19     else if (x < 1000000) t = 5;
20     else if (x < 10000000) t = 6;
21     else if (x < 100000000) t = 7;
22     else if (x < 1000000000) t = 8;
23     else t = 9;
24
25     while (t >= 0)
26     {
27         p2 = t;
28         p = 1;
29         while (p2--) p *= 10;
30         n = x / p;
31         x -= n * p;
32         if (!n)
33         {
34             DBG_1_ON;
35             DBG_1_OFF;
36             DBG_1_ON;
37             DBG_1_OFF;
38             n--;
39         }
40         else
41         {
42             while (n > 0)
43             {
44                 DBG_1_ON;
45                 DBG_1_OFF;
46                 n--;
47             }
48         }
49
50         t--;
51     }
52
53     for (w = DBG_PAUSE; w; w--); //Long pause after number is complete
54 }
55
56 //Display unsigned 32-bit number through debug led
57 //Read as follows: 1230 = [*]  [* *]  [* * *]  [**]  (note zero is fast double flash)
58 #define DLED_ONTIME 1000000
59 #define DLED_PAUSE 1500000
60 void dled_print(uint32_t x, uint8_t long_pause)
61 {
62     int8_t t;
63     uint32_t n;
64     uint32_t p, p2;
65
66     if      (x < 10) t = 0;
67     else if (x < 100) t = 1;
68     else if (x < 1000) t = 2;
69     else if (x < 10000) t = 3;
70     else if (x < 100000) t = 4;
71     else if (x < 1000000) t = 5;
72     else if (x < 10000000) t = 6;
73     else if (x < 100000000) t = 7;
74     else if (x < 1000000000) t = 8;
75     else t = 9;
76
77     while (t >= 0)
78     {
79         p2 = t;
80         p = 1;
81         while (p2--) p *= 10;
82         n = x / p;
83         x -= n * p;
84         if (!n)
85         {
86             DBG_LED_ON;
87             for (w = DLED_ONTIME / 4; w; w--);
88             DBG_LED_OFF;
89             for (w = DLED_ONTIME / 4; w; w--);
90             DBG_LED_ON;
91             for (w = DLED_ONTIME / 4; w; w--);
92             DBG_LED_OFF;
93             for (w = DLED_ONTIME / 4; w; w--);
94             n--;
95         }
96         else
97         {
98             while (n > 0)
99             {
100                 DBG_LED_ON;
101                 for (w = DLED_ONTIME; w; w--);
102                 DBG_LED_OFF;
103                 for (w = DLED_ONTIME / 2; w; w--);
104                 n--;
105             }
106         }
107
108         for (w = DLED_PAUSE; w; w--);
109         t--;
110     }
111
112     if (long_pause)
113     {
114         for (w = DLED_PAUSE * 4; w; w--);
115     }
116 }
117
118 #ifdef DEBUG_BOOT_TRACING_ENABLE
119
120 volatile uint32_t debug_code;
121
122 //These macros are for compile time substitution
123 #define DEBUG_BOOT_TRACING_EXTINTn (DEBUG_BOOT_TRACING_PIN % _U_(0x10))
124 #define DEBUG_BOOT_TRACING_EXTINTb (_U_(0x1) << DEBUG_BOOT_TRACING_EXTINTn)
125 #define DEBUG_BOOT_TRACING_CONFIG_INDn (DEBUG_BOOT_TRACING_EXTINTn / _U_(0x8))
126 #define DEBUG_BOOT_TRACING_CONFIG_SENSEn (DEBUG_BOOT_TRACING_EXTINTn % _U_(0x8))
127 #define DEBUG_BOOT_TRACING_CONFIG_SENSEb (DEBUG_BOOT_TRACING_CONFIG_SENSEn * _U_(0x4))
128 #define DEBUG_BOOT_TRACING_IRQn (EIC_0_IRQn + DEBUG_BOOT_TRACING_EXTINTn)
129
130 //These macros perform PORT+PIN definition translation to IRQn in the preprocessor
131 #define PORTPIN_TO_IRQn_EXPAND(def) def
132 #define PORTPIN_TO_IRQn_DEF(def) PORTPIN_TO_IRQn_EXPAND(def)
133 #if DEBUG_BOOT_TRACING_PIN < 10
134 #define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_ ## port ## 0 ## pin ## A_EIC_EXTINT_NUM)
135 #else
136 #define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_ ## port ## pin ## A_EIC_EXTINT_NUM)
137 #endif
138 #define PORTPIN_TO_IRQn(port, pin) PORTPIN_TO_IRQn_TODEF(port, pin)
139
140 //These macros perform function name output in the preprocessor
141 #define DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq) void EIC_ ## irq ## _Handler(void)
142 #define DEBUG_BOOT_TRACING_HANDLER(irq) DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq)
143
144 //To generate the function name of the IRQ handler catching boot tracing,
145 //  certain macros must be undefined, so save their current values to macro stack
146 #pragma push_macro("PA")
147 #pragma push_macro("PB")
148 #pragma push_macro("_L_")
149
150 //Undefine / redefine pushed macros
151 #undef PA
152 #undef PB
153 #undef _L_
154 #define _L_(x) x
155
156 //Perform the work and output
157 //Ex: PORT PB, PIN 31 = void EIC_15_Handler(void)
158 DEBUG_BOOT_TRACING_HANDLER(PORTPIN_TO_IRQn(DEBUG_BOOT_TRACING_PORT, DEBUG_BOOT_TRACING_PIN))
159
160 //Restore macros
161 #pragma pop_macro("PA")
162 #pragma pop_macro("PB")
163 #pragma pop_macro("_L_")
164 {
165     //This is only for non-functional keyboard troubleshooting and should be disabled after boot
166     //Intention is to lock up the keyboard here with repeating debug led code
167     while (1)
168     {
169         dled_print(debug_code, 1);
170     }
171 }
172
173 void debug_code_init(void)
174 {
175     DBGC(DC_UNSET);
176
177     //Configure Ports for EIC
178     PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Input
179     PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTSET.reg = 1 << DEBUG_BOOT_TRACING_PIN; //High
180     PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 1; //Input Enable
181     PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 1; //Pull Enable
182     PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 1; //Mux Enable
183     PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; //Mux A
184
185     //Enable CLK_EIC_APB
186     MCLK->APBAMASK.bit.EIC_ = 1;
187
188     //Configure EIC
189     EIC->CTRLA.bit.SWRST = 1;
190     while (EIC->SYNCBUSY.bit.SWRST) {}
191     EIC->ASYNCH.reg = DEBUG_BOOT_TRACING_EXTINTb;
192     EIC->INTENSET.reg = DEBUG_BOOT_TRACING_EXTINTb;
193     EIC->CONFIG[DEBUG_BOOT_TRACING_CONFIG_INDn].reg |= (EIC_CONFIG_SENSE0_FALL_Val << DEBUG_BOOT_TRACING_CONFIG_SENSEb);
194     EIC->CTRLA.bit.ENABLE = 1;
195     while (EIC->SYNCBUSY.bit.ENABLE) {}
196
197     //Enable EIC IRQ
198     NVIC_EnableIRQ(DEBUG_BOOT_TRACING_IRQn);
199 }
200
201 void debug_code_disable(void)
202 {
203     //Disable EIC IRQ
204     NVIC_DisableIRQ(DEBUG_BOOT_TRACING_IRQn);
205
206     //Disable EIC
207     EIC->CTRLA.bit.ENABLE = 0;
208     while (EIC->SYNCBUSY.bit.ENABLE) {}
209
210     //Default port configuration
211     PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Input
212     PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Low
213     PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 0; //Input Disable
214     PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 0; //Pull Disable
215     PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 0; //Mux Disable
216     PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; //Mux A
217
218     //Disable CLK_EIC_APB
219     MCLK->APBAMASK.bit.EIC_ = 0;
220 }
221
222 #else
223
224 void debug_code_init(void) {}
225 void debug_code_disable(void) {}
226
227 #endif //DEBUG_BOOT_TRACING_ENABLE