]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/arm_atsam/i2c_master.c
f608a79cc98d1e22e0144fd2af0f4868b8687462
[qmk_firmware.git] / tmk_core / protocol / arm_atsam / i2c_master.c
1 /*
2 Copyright 2018 Massdrop Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "arm_atsam_protocol.h"
19
20 #ifndef MD_BOOTLOADER
21
22 #include <string.h>
23
24 //From keyboard
25 #include "config.h"
26 #include "config_led.h"
27 #include "matrix.h"
28
29 #define I2C_LED_USE_DMA 1               //Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers
30
31 static uint8_t i2c_led_q[I2C_Q_SIZE];   //I2C queue circular buffer
32 static uint8_t i2c_led_q_s;             //Start of circular buffer
33 static uint8_t i2c_led_q_e;             //End of circular buffer
34 static uint8_t i2c_led_q_full;          //Queue full counter for reset
35
36 static uint8_t dma_sendbuf[I2C_DMA_MAX_SEND]; //Data being written to I2C
37
38 volatile uint8_t i2c_led_q_running;
39
40 #endif //MD_BOOTLOADER
41
42 void i2c0_init(void)
43 {
44     DBGC(DC_I2C0_INIT_BEGIN);
45
46     CLK_set_i2c0_freq(CHAN_SERCOM_I2C0, FREQ_I2C0_DEFAULT);
47
48     //MCU
49     PORT->Group[0].PMUX[4].bit.PMUXE = 2;
50     PORT->Group[0].PMUX[4].bit.PMUXO = 2;
51     PORT->Group[0].PINCFG[8].bit.PMUXEN = 1;
52     PORT->Group[0].PINCFG[9].bit.PMUXEN = 1;
53
54     //I2C
55     //Note: SW Reset handled in CLK_set_i2c0_freq clks.c
56
57     SERCOM0->I2CM.CTRLA.bit.MODE = 5;                           //Set master mode
58
59     SERCOM0->I2CM.CTRLA.bit.SPEED = 0;                          //Set to 1 for Fast-mode Plus (FM+) up to 1 MHz
60     SERCOM0->I2CM.CTRLA.bit.RUNSTDBY = 1;                       //Enabled
61
62     SERCOM0->I2CM.CTRLA.bit.ENABLE = 1;                         //Enable the device
63     while (SERCOM0->I2CM.SYNCBUSY.bit.ENABLE) { DBGC(DC_I2C0_INIT_SYNC_ENABLING); }                //Wait for SYNCBUSY.ENABLE to clear
64
65     SERCOM0->I2CM.STATUS.bit.BUSSTATE = 1;                      //Force into IDLE state
66     while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_I2C0_INIT_SYNC_SYSOP); }
67     while (SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1) { DBGC(DC_I2C0_INIT_WAIT_IDLE); }           //Wait while not idle
68
69     DBGC(DC_I2C0_INIT_COMPLETE);
70 }
71
72 uint8_t i2c0_start(uint8_t address)
73 {
74     SERCOM0->I2CM.ADDR.bit.ADDR = address;
75     while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {}
76     while (SERCOM0->I2CM.INTFLAG.bit.MB == 0) {}
77     while (SERCOM0->I2CM.STATUS.bit.RXNACK) {}
78
79     return 1;
80 }
81
82 uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)
83 {
84     if (!length) return 0;
85
86     i2c0_start(address);
87
88     while (length)
89     {
90         SERCOM0->I2CM.DATA.bit.DATA = *data;
91         while (SERCOM0->I2CM.INTFLAG.bit.MB == 0) {}
92         while (SERCOM0->I2CM.STATUS.bit.RXNACK) {}
93
94         data++;
95         length--;
96     }
97
98     i2c0_stop();
99
100     return 1;
101 }
102
103 void i2c0_stop(void)
104 {
105     if (SERCOM0->I2CM.STATUS.bit.CLKHOLD || SERCOM0->I2CM.INTFLAG.bit.MB == 1 || SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1)
106     {
107         SERCOM0->I2CM.CTRLB.bit.CMD = 3;
108         while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP);
109         while (SERCOM0->I2CM.STATUS.bit.CLKHOLD);
110         while (SERCOM0->I2CM.INTFLAG.bit.MB);
111         while (SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1);
112     }
113 }
114
115 #ifndef MD_BOOTLOADER
116 void i2c1_init(void)
117 {
118     DBGC(DC_I2C1_INIT_BEGIN);
119
120     CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
121
122     /* MCU */
123     PORT->Group[0].PMUX[8].bit.PMUXE = 2;
124     PORT->Group[0].PMUX[8].bit.PMUXO = 2;
125     PORT->Group[0].PINCFG[16].bit.PMUXEN = 1;
126     PORT->Group[0].PINCFG[17].bit.PMUXEN = 1;
127
128     /* I2C */
129     //Note: SW Reset handled in CLK_set_i2c1_freq clks.c
130
131     SERCOM1->I2CM.CTRLA.bit.MODE = 5;                   //MODE: Set master mode (No sync)
132     SERCOM1->I2CM.CTRLA.bit.SPEED = 1;                  //SPEED: Fm+ up to 1MHz (No sync)
133     SERCOM1->I2CM.CTRLA.bit.RUNSTDBY = 1;               //RUNSTBY: Enabled (No sync)
134
135     SERCOM1->I2CM.CTRLB.bit.SMEN = 1;                   //SMEN: Smart mode enabled (For DMA)(No sync)
136
137     NVIC_EnableIRQ(SERCOM1_0_IRQn);
138     SERCOM1->I2CM.INTENSET.bit.ERROR = 1;
139
140     SERCOM1->I2CM.CTRLA.bit.ENABLE = 1;                 //ENABLE: Enable the device (sync SYNCBUSY.ENABLE)
141     while (SERCOM1->I2CM.SYNCBUSY.bit.ENABLE) { DBGC(DC_I2C1_INIT_SYNC_ENABLING); }        //Wait for SYNCBUSY.ENABLE to clear
142
143     SERCOM1->I2CM.STATUS.bit.BUSSTATE = 1;              //BUSSTATE: Force into IDLE state (sync SYNCBUSY.SYSOP)
144     while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_I2C1_INIT_SYNC_SYSOP); }
145     while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1) { DBGC(DC_I2C1_INIT_WAIT_IDLE); }  //Wait while not idle
146
147     DBGC(DC_I2C1_INIT_COMPLETE);
148 }
149
150 uint8_t i2c1_start(uint8_t address)
151 {
152     SERCOM1->I2CM.ADDR.bit.ADDR = address;
153     while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP) {}
154     while (SERCOM1->I2CM.INTFLAG.bit.MB == 0) {}
155     while (SERCOM1->I2CM.STATUS.bit.RXNACK) {}
156
157     return 1;
158 }
159
160 uint8_t i2c1_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)
161 {
162     if (!length) return 0;
163
164     i2c1_start(address);
165
166     while (length)
167     {
168         SERCOM1->I2CM.DATA.bit.DATA = *data;
169         while (SERCOM1->I2CM.INTFLAG.bit.MB == 0) {}
170         while (SERCOM1->I2CM.STATUS.bit.RXNACK) {}
171
172         data++;
173         length--;
174     }
175
176     i2c1_stop();
177
178     return 1;
179 }
180
181 void i2c1_stop(void)
182 {
183     if (SERCOM1->I2CM.STATUS.bit.CLKHOLD || SERCOM1->I2CM.INTFLAG.bit.MB == 1 || SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1)
184     {
185         SERCOM1->I2CM.CTRLB.bit.CMD = 3;
186         while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP);
187         while (SERCOM1->I2CM.STATUS.bit.CLKHOLD);
188         while (SERCOM1->I2CM.INTFLAG.bit.MB);
189         while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1);
190     }
191 }
192
193 void i2c_led_send_CRWL(uint8_t drvid)
194 {
195     uint8_t i2cdata[] = { ISSI3733_CMDRWL, ISSI3733_CMDRWL_WRITE_ENABLE_ONCE };
196     i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
197 }
198
199 void i2c_led_select_page(uint8_t drvid, uint8_t pageno)
200 {
201     uint8_t i2cdata[] = { ISSI3733_CMDR, pageno };
202     i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
203 }
204
205 void i2c_led_send_GCR(uint8_t drvid)
206 {
207     uint8_t i2cdata[] = { ISSI3733_GCCR, 0x00 };
208
209     if (gcr_actual > LED_GCR_MAX) gcr_actual = LED_GCR_MAX;
210     i2cdata[1] = gcr_actual;
211
212     i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
213 }
214
215 void i2c_led_send_onoff(uint8_t drvid)
216 {
217 #if I2C_LED_USE_DMA != 1
218     if (!i2c_led_q_running)
219     {
220 #endif
221         i2c_led_send_CRWL(drvid);
222         i2c_led_select_page(drvid, 0);
223 #if I2C_LED_USE_DMA != 1
224     }
225 #endif
226
227     *issidrv[drvid].onoff = 0; //Force start location offset to zero
228     i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].onoff, ISSI3733_PG0_BYTES, 0);
229 }
230
231 void i2c_led_send_mode_op_gcr(uint8_t drvid, uint8_t mode, uint8_t operation)
232 {
233     uint8_t i2cdata[] = { ISSI3733_CR, mode | operation, gcr_actual};
234     i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
235 }
236
237 void i2c_led_send_pur_pdr(uint8_t drvid, uint8_t pur, uint8_t pdr)
238 {
239     uint8_t i2cdata[] = { ISSI3733_SWYR_PUR, pur, pdr };
240
241     i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
242 }
243
244 void i2c_led_send_pwm(uint8_t drvid)
245 {
246 #if I2C_LED_USE_DMA != 1
247     if (!i2c_led_q_running)
248     {
249 #endif
250         i2c_led_send_CRWL(drvid);
251         i2c_led_select_page(drvid, 0);
252 #if I2C_LED_USE_DMA != 1
253     }
254 #endif
255
256     *issidrv[drvid].pwm = 0; //Force start location offset to zero
257     i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].pwm, ISSI3733_PG1_BYTES, 0);
258 }
259
260 uint8_t I2C3733_Init_Control(void)
261 {
262     DBGC(DC_I2C3733_INIT_CONTROL_BEGIN);
263
264     //Hardware state shutdown on boot
265     //USB state machine will enable driver when communication is ready
266     I2C3733_Control_Set(0);
267
268     CLK_delay_ms(1);
269
270     sr_exp_data.bit.IRST = 0;
271     SR_EXP_WriteData();
272
273     CLK_delay_ms(1);
274
275     DBGC(DC_I2C3733_INIT_CONTROL_COMPLETE);
276
277     return 1;
278 }
279
280 uint8_t I2C3733_Init_Drivers(void)
281 {
282     DBGC(DC_I2C3733_INIT_DRIVERS_BEGIN);
283
284     gcr_actual = ISSI3733_GCR_DEFAULT;
285     gcr_actual_last = gcr_actual;
286
287     if (gcr_actual > LED_GCR_MAX) gcr_actual = LED_GCR_MAX;
288     gcr_desired = gcr_actual;
289
290     //Set up master device
291     i2c_led_send_CRWL(0);
292     i2c_led_select_page(0, 3);
293     i2c_led_send_mode_op_gcr(0, 0, ISSI3733_CR_SSD_NORMAL); //No SYNC due to brightness mismatch with second driver
294
295     //Set up slave device
296     i2c_led_send_CRWL(1);
297     i2c_led_select_page(1, 3);
298     i2c_led_send_mode_op_gcr(1, 0, ISSI3733_CR_SSD_NORMAL); //No SYNC due to brightness mismatch with first driver and slight flicker at rgb values 1,2
299
300     i2c_led_send_CRWL(0);
301     i2c_led_select_page(0, 3);
302     i2c_led_send_pur_pdr(0, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
303
304     i2c_led_send_CRWL(1);
305     i2c_led_select_page(1, 3);
306     i2c_led_send_pur_pdr(1, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
307
308     DBGC(DC_I2C3733_INIT_DRIVERS_COMPLETE);
309
310     return 1;
311 }
312
313 void I2C_DMAC_LED_Init(void)
314 {
315     Dmac *dmac = DMAC;
316
317     DBGC(DC_I2C_DMAC_LED_INIT_BEGIN);
318
319     //Disable device
320     dmac->CTRL.bit.DMAENABLE = 0;                   //Disable DMAC
321     while (dmac->CTRL.bit.DMAENABLE) {}             //Wait for disabled state in case of ongoing transfers
322     dmac->CTRL.bit.SWRST = 1;                       //Software Reset DMAC
323     while (dmac->CTRL.bit.SWRST) {}                 //Wait for software reset to complete
324
325     //Configure device
326     dmac->BASEADDR.reg = (uint32_t)&dmac_desc;      //Set descriptor base address
327     dmac->WRBADDR.reg = (uint32_t)&dmac_desc_wb;    //Set descriptor write back address
328     dmac->CTRL.reg |= 0x0f00;                       //Handle all priorities (LVL0-3)
329
330     //Disable channel
331     dmac->Channel[0].CHCTRLA.bit.ENABLE = 0;        //Disable the channel
332     while (dmac->Channel[0].CHCTRLA.bit.ENABLE) {}  //Wait for disabled state in case of ongoing transfers
333     dmac->Channel[0].CHCTRLA.bit.SWRST = 1;         //Software Reset the channel
334     while (dmac->Channel[0].CHCTRLA.bit.SWRST) {}   //Wait for software reset to complete
335
336     //Configure channel
337     dmac->Channel[0].CHCTRLA.bit.THRESHOLD = 0;     //1BEAT
338     dmac->Channel[0].CHCTRLA.bit.BURSTLEN = 0;      //SINGLE
339     dmac->Channel[0].CHCTRLA.bit.TRIGACT = 2;       //BURST
340     dmac->Channel[0].CHCTRLA.bit.TRIGSRC = SERCOM1_DMAC_ID_TX;  //Trigger source
341     dmac->Channel[0].CHCTRLA.bit.RUNSTDBY = 1;      //Run in standby
342
343     NVIC_EnableIRQ(DMAC_0_IRQn);
344     dmac->Channel[0].CHINTENSET.bit.TCMPL = 1;
345     dmac->Channel[0].CHINTENSET.bit.TERR = 1;
346
347     //Enable device
348     dmac->CTRL.bit.DMAENABLE = 1;                   //Enable DMAC
349     while (dmac->CTRL.bit.DMAENABLE == 0) {}        //Wait for enable state
350
351     DBGC(DC_I2C_DMAC_LED_INIT_COMPLETE);
352 }
353
354 //state = 1 enable
355 //state = 0 disable
356 void I2C3733_Control_Set(uint8_t state)
357 {
358     DBGC(DC_I2C3733_CONTROL_SET_BEGIN);
359
360     sr_exp_data.bit.SDB_N = (state == 1 ? 1 : 0);
361     SR_EXP_WriteData();
362
363     DBGC(DC_I2C3733_CONTROL_SET_COMPLETE);
364 }
365
366 void i2c_led_desc_defaults(void)
367 {
368     dmac_desc.BTCTRL.bit.STEPSIZE = 0;      //SRCINC used in favor for auto 1 inc
369     dmac_desc.BTCTRL.bit.STEPSEL = 0;       //SRCINC used in favor for auto 1 inc
370     dmac_desc.BTCTRL.bit.DSTINC = 0;        //The Destination Address Increment is disabled
371     dmac_desc.BTCTRL.bit.SRCINC = 1;        //The Source Address Increment is enabled (Inc by 1)
372     dmac_desc.BTCTRL.bit.BEATSIZE = 0;      //8-bit bus transfer
373     dmac_desc.BTCTRL.bit.BLOCKACT = 0;      //Channel will be disabled if it is the last block transfer in the transaction
374     dmac_desc.BTCTRL.bit.EVOSEL = 0;        //Event generation disabled
375     dmac_desc.BTCTRL.bit.VALID = 1;         //Set dmac valid
376 }
377
378 void i2c_led_prepare_send_dma(uint8_t *data, uint8_t len)
379 {
380     i2c_led_desc_defaults();
381
382     dmac_desc.BTCNT.reg = len;
383     dmac_desc.SRCADDR.reg = (uint32_t)data + len;
384     dmac_desc.DSTADDR.reg = (uint32_t)&SERCOM1->I2CM.DATA.reg;
385     dmac_desc.DESCADDR.reg = 0;
386 }
387
388 void i2c_led_begin_dma(uint8_t drvid)
389 {
390     DMAC->Channel[0].CHCTRLA.bit.ENABLE = 1; //Enable the channel
391
392     SERCOM1->I2CM.ADDR.reg = (dmac_desc.BTCNT.reg << 16) | 0x2000 | issidrv[drvid].addr; //Begin transfer
393 }
394
395 void i2c_led_send_CRWL_dma(uint8_t drvid)
396 {
397     *(dma_sendbuf+0) = ISSI3733_CMDRWL;
398     *(dma_sendbuf+1) = ISSI3733_CMDRWL_WRITE_ENABLE_ONCE;
399     i2c_led_prepare_send_dma(dma_sendbuf, 2);
400
401     i2c_led_begin_dma(drvid);
402 }
403
404 void i2c_led_select_page_dma(uint8_t drvid, uint8_t pageno)
405 {
406     *(dma_sendbuf+0) = ISSI3733_CMDR;
407     *(dma_sendbuf+1) = pageno;
408     i2c_led_prepare_send_dma(dma_sendbuf, 2);
409
410     i2c_led_begin_dma(drvid);
411 }
412
413 void i2c_led_send_GCR_dma(uint8_t drvid)
414 {
415     *(dma_sendbuf+0) = ISSI3733_GCCR;
416     *(dma_sendbuf+1) = gcr_actual;
417     i2c_led_prepare_send_dma(dma_sendbuf, 2);
418
419     i2c_led_begin_dma(drvid);
420 }
421
422 void i2c_led_send_pwm_dma(uint8_t drvid)
423 {
424     //Note: This copies the CURRENT pwm buffer, which may be getting modified
425     memcpy(dma_sendbuf, issidrv[drvid].pwm, ISSI3733_PG1_BYTES);
426     *dma_sendbuf = 0; //Force start location offset to zero
427     i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG1_BYTES);
428
429     i2c_led_begin_dma(drvid);
430 }
431
432 void i2c_led_send_onoff_dma(uint8_t drvid)
433 {
434     //Note: This copies the CURRENT onoff buffer, which may be getting modified
435     memcpy(dma_sendbuf, issidrv[drvid].onoff, ISSI3733_PG0_BYTES);
436     *dma_sendbuf = 0; //Force start location offset to zero
437     i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG0_BYTES);
438
439     i2c_led_begin_dma(drvid);
440 }
441
442 void i2c_led_q_init(void)
443 {
444     memset(i2c_led_q, 0, I2C_Q_SIZE);
445     i2c_led_q_s = 0;
446     i2c_led_q_e = 0;
447     i2c_led_q_running = 0;
448     i2c_led_q_full = 0;
449 }
450
451 uint8_t i2c_led_q_isempty(void)
452 {
453     return i2c_led_q_s == i2c_led_q_e;
454 }
455
456 uint8_t i2c_led_q_size(void)
457 {
458     return (i2c_led_q_e - i2c_led_q_s) % I2C_Q_SIZE;
459 }
460
461 uint8_t i2c_led_q_available(void)
462 {
463     return I2C_Q_SIZE - i2c_led_q_size() - 1; //Never allow end to meet start
464 }
465
466 void i2c_led_q_add(uint8_t cmd)
467 {
468     //WARNING: Always request room before adding commands!
469
470     //Assign command
471     i2c_led_q[i2c_led_q_e] = cmd;
472
473     i2c_led_q_e = (i2c_led_q_e + 1) % I2C_Q_SIZE; //Move end up one or wrap
474 }
475
476 void i2c_led_q_s_advance(void)
477 {
478     i2c_led_q_s = (i2c_led_q_s + 1) % I2C_Q_SIZE; //Move start up one or wrap
479 }
480
481 //Always request room before adding commands
482 //PS: In case the queue somehow gets filled, it will reset if it can not clear up
483 //PS: Could only get this to happen through unrealistic timings to overload the I2C bus
484 uint8_t i2c_led_q_request_room(uint8_t request_size)
485 {
486     if (request_size > i2c_led_q_available())
487     {
488         i2c_led_q_full++;
489
490         if (i2c_led_q_full >= 100) //Give the queue a chance to clear up
491         {
492             DBG_LED_ON;
493             I2C_DMAC_LED_Init();
494             i2c_led_q_init();
495             return 1;
496         }
497
498         return 0;
499     }
500
501     i2c_led_q_full = 0;
502
503     return 1;
504 }
505
506 uint8_t i2c_led_q_run(void)
507 {
508     if (i2c_led_q_isempty())
509     {
510         i2c_led_q_running = 0;
511         return 0;
512     }
513
514     if (i2c_led_q_running) return 1;
515
516     i2c_led_q_running = 1;
517
518 #if I2C_LED_USE_DMA != 1
519     while (!i2c_led_q_isempty())
520     {
521 #endif
522         //run command
523         if (i2c_led_q[i2c_led_q_s] == I2C_Q_CRWL)
524         {
525             i2c_led_q_s_advance();
526             uint8_t drvid = i2c_led_q[i2c_led_q_s];
527 #if I2C_LED_USE_DMA == 1
528             i2c_led_send_CRWL_dma(drvid);
529 #else
530             i2c_led_send_CRWL(drvid);
531 #endif
532         }
533         else if (i2c_led_q[i2c_led_q_s] == I2C_Q_PAGE_SELECT)
534         {
535             i2c_led_q_s_advance();
536             uint8_t drvid = i2c_led_q[i2c_led_q_s];
537             i2c_led_q_s_advance();
538             uint8_t page = i2c_led_q[i2c_led_q_s];
539 #if I2C_LED_USE_DMA == 1
540             i2c_led_select_page_dma(drvid, page);
541 #else
542             i2c_led_select_page(drvid, page);
543 #endif
544         }
545         else if (i2c_led_q[i2c_led_q_s] == I2C_Q_PWM)
546         {
547             i2c_led_q_s_advance();
548             uint8_t drvid = i2c_led_q[i2c_led_q_s];
549 #if I2C_LED_USE_DMA == 1
550             i2c_led_send_pwm_dma(drvid);
551 #else
552             i2c_led_send_pwm(drvid);
553 #endif
554         }
555         else if (i2c_led_q[i2c_led_q_s] == I2C_Q_GCR)
556         {
557             i2c_led_q_s_advance();
558             uint8_t drvid = i2c_led_q[i2c_led_q_s];
559 #if I2C_LED_USE_DMA == 1
560             i2c_led_send_GCR_dma(drvid);
561 #else
562             i2c_led_send_GCR(drvid);
563 #endif
564         }
565         else if (i2c_led_q[i2c_led_q_s] == I2C_Q_ONOFF)
566         {
567             i2c_led_q_s_advance();
568             uint8_t drvid = i2c_led_q[i2c_led_q_s];
569 #if I2C_LED_USE_DMA == 1
570             i2c_led_send_onoff_dma(drvid);
571 #else
572             i2c_led_send_onoff(drvid);
573 #endif
574         }
575
576         i2c_led_q_s_advance(); //Advance last run command or if the command byte was not serviced
577
578 #if I2C_LED_USE_DMA != 1
579     }
580
581     i2c_led_q_running = 0;
582 #endif
583
584     return 1;
585 }
586 #endif //MD_BOOTLOADER