aboutsummaryrefslogtreecommitdiff
path: root/quantum/light_ws2812.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/light_ws2812.c')
-rwxr-xr-xquantum/light_ws2812.c164
1 files changed, 158 insertions, 6 deletions
diff --git a/quantum/light_ws2812.c b/quantum/light_ws2812.c
index 401845e85..2506e3d8e 100755
--- a/quantum/light_ws2812.c
+++ b/quantum/light_ws2812.c
@@ -7,7 +7,18 @@
7* Jan 18th, 2014 v2.0b Initial Version 7* Jan 18th, 2014 v2.0b Initial Version
8* Nov 29th, 2015 v2.3 Added SK6812RGBW support 8* Nov 29th, 2015 v2.3 Added SK6812RGBW support
9* 9*
10* License: GNU GPL v2 (see License.txt) 10* This program is free software: you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by
12* the Free Software Foundation, either version 2 of the License, or
13* (at your option) any later version.
14*
15* This program is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more details.
19*
20* You should have received a copy of the GNU General Public License
21* along with this program. If not, see <http://www.gnu.org/licenses/>.
11*/ 22*/
12 23
13#include "light_ws2812.h" 24#include "light_ws2812.h"
@@ -16,14 +27,128 @@
16#include <util/delay.h> 27#include <util/delay.h>
17#include "debug.h" 28#include "debug.h"
18 29
30#ifdef RGBW_BB_TWI
31
32// Port for the I2C
33#define I2C_DDR DDRD
34#define I2C_PIN PIND
35#define I2C_PORT PORTD
36
37// Pins to be used in the bit banging
38#define I2C_CLK 0
39#define I2C_DAT 1
40
41#define I2C_DATA_HI()\
42I2C_DDR &= ~ (1 << I2C_DAT);\
43I2C_PORT |= (1 << I2C_DAT);
44#define I2C_DATA_LO()\
45I2C_DDR |= (1 << I2C_DAT);\
46I2C_PORT &= ~ (1 << I2C_DAT);
47
48#define I2C_CLOCK_HI()\
49I2C_DDR &= ~ (1 << I2C_CLK);\
50I2C_PORT |= (1 << I2C_CLK);
51#define I2C_CLOCK_LO()\
52I2C_DDR |= (1 << I2C_CLK);\
53I2C_PORT &= ~ (1 << I2C_CLK);
54
55#define I2C_DELAY 1
56
57void I2C_WriteBit(unsigned char c)
58{
59 if (c > 0)
60 {
61 I2C_DATA_HI();
62 }
63 else
64 {
65 I2C_DATA_LO();
66 }
67
68 I2C_CLOCK_HI();
69 _delay_us(I2C_DELAY);
70
71 I2C_CLOCK_LO();
72 _delay_us(I2C_DELAY);
73
74 if (c > 0)
75 {
76 I2C_DATA_LO();
77 }
78
79 _delay_us(I2C_DELAY);
80}
81
82// Inits bitbanging port, must be called before using the functions below
83//
84void I2C_Init(void)
85{
86 I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
87
88 I2C_CLOCK_HI();
89 I2C_DATA_HI();
90
91 _delay_us(I2C_DELAY);
92}
93
94// Send a START Condition
95//
96void I2C_Start(void)
97{
98 // set both to high at the same time
99 I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
100 _delay_us(I2C_DELAY);
101
102 I2C_DATA_LO();
103 _delay_us(I2C_DELAY);
104
105 I2C_CLOCK_LO();
106 _delay_us(I2C_DELAY);
107}
108
109// Send a STOP Condition
110//
111void I2C_Stop(void)
112{
113 I2C_CLOCK_HI();
114 _delay_us(I2C_DELAY);
115
116 I2C_DATA_HI();
117 _delay_us(I2C_DELAY);
118}
119
120// write a byte to the I2C slave device
121//
122unsigned char I2C_Write(unsigned char c)
123{
124 for (char i = 0; i < 8; i++)
125 {
126 I2C_WriteBit(c & 128);
127
128 c <<= 1;
129 }
130
131
132 I2C_WriteBit(0);
133 _delay_us(I2C_DELAY);
134 _delay_us(I2C_DELAY);
135
136 // _delay_us(I2C_DELAY);
137 //return I2C_ReadBit();
138 return 0;
139}
140
141
142#endif
143
19// Setleds for standard RGB 144// Setleds for standard RGB
20void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds) 145void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds)
21{ 146{
22 // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); 147 // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
23 ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF)); 148 ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF));
24} 149}
25 150
26void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask) 151void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask)
27{ 152{
28 // ws2812_DDRREG |= pinmask; // Enable DDR 153 // ws2812_DDRREG |= pinmask; // Enable DDR
29 // new universal format (DDR) 154 // new universal format (DDR)
@@ -34,14 +159,41 @@ void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pin
34} 159}
35 160
36// Setleds for SK6812RGBW 161// Setleds for SK6812RGBW
37void inline ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds) 162void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds)
38{ 163{
164
165 #ifdef RGBW_BB_TWI
166 uint8_t sreg_prev, twcr_prev;
167 sreg_prev=SREG;
168 twcr_prev=TWCR;
169 cli();
170 TWCR &= ~(1<<TWEN);
171 I2C_Init();
172 I2C_Start();
173 I2C_Write(0x84);
174 uint16_t datlen = leds<<2;
175 uint8_t curbyte;
176 uint8_t * data = (uint8_t*)ledarray;
177 while (datlen--) {
178 curbyte=*data++;
179 I2C_Write(curbyte);
180 }
181 I2C_Stop();
182 SREG=sreg_prev;
183 TWCR=twcr_prev;
184 #endif
185
186
39 // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR 187 // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
40 // new universal format (DDR) 188 // new universal format (DDR)
41 _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF); 189 _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF);
42 190
43 ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF)); 191 ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF));
44 _delay_us(80); 192
193
194 #ifndef RGBW_BB_TWI
195 _delay_us(80);
196 #endif
45} 197}
46 198
47void ws2812_sendarray(uint8_t *data,uint16_t datlen) 199void ws2812_sendarray(uint8_t *data,uint16_t datlen)
@@ -123,7 +275,7 @@ void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
123 cli(); 275 cli();
124 276
125 while (datlen--) { 277 while (datlen--) {
126 curbyte=*data++; 278 curbyte=(*data++);
127 279
128 asm volatile( 280 asm volatile(
129 " ldi %0,8 \n\t" 281 " ldi %0,8 \n\t"