summaryrefslogtreecommitdiffstats
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 401845e855..2506e3d8ec 100755
--- a/quantum/light_ws2812.c
+++ b/quantum/light_ws2812.c
@@ -7,7 +7,18 @@
* Jan 18th, 2014 v2.0b Initial Version
* Nov 29th, 2015 v2.3 Added SK6812RGBW support
*
-* License: GNU GPL v2 (see License.txt)
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "light_ws2812.h"
@@ -16,14 +27,128 @@
#include <util/delay.h>
#include "debug.h"
+#ifdef RGBW_BB_TWI
+
+// Port for the I2C
+#define I2C_DDR DDRD
+#define I2C_PIN PIND
+#define I2C_PORT PORTD
+
+// Pins to be used in the bit banging
+#define I2C_CLK 0
+#define I2C_DAT 1
+
+#define I2C_DATA_HI()\
+I2C_DDR &= ~ (1 << I2C_DAT);\
+I2C_PORT |= (1 << I2C_DAT);
+#define I2C_DATA_LO()\
+I2C_DDR |= (1 << I2C_DAT);\
+I2C_PORT &= ~ (1 << I2C_DAT);
+
+#define I2C_CLOCK_HI()\
+I2C_DDR &= ~ (1 << I2C_CLK);\
+I2C_PORT |= (1 << I2C_CLK);
+#define I2C_CLOCK_LO()\
+I2C_DDR |= (1 << I2C_CLK);\
+I2C_PORT &= ~ (1 << I2C_CLK);
+
+#define I2C_DELAY 1
+
+void I2C_WriteBit(unsigned char c)
+{
+ if (c > 0)
+ {
+ I2C_DATA_HI();
+ }
+ else
+ {
+ I2C_DATA_LO();
+ }
+
+ I2C_CLOCK_HI();
+ _delay_us(I2C_DELAY);
+
+ I2C_CLOCK_LO();
+ _delay_us(I2C_DELAY);
+
+ if (c > 0)
+ {
+ I2C_DATA_LO();
+ }
+
+ _delay_us(I2C_DELAY);
+}
+
+// Inits bitbanging port, must be called before using the functions below
+//
+void I2C_Init(void)
+{
+ I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
+
+ I2C_CLOCK_HI();
+ I2C_DATA_HI();
+
+ _delay_us(I2C_DELAY);
+}
+
+// Send a START Condition
+//
+void I2C_Start(void)
+{
+ // set both to high at the same time
+ I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
+ _delay_us(I2C_DELAY);
+
+ I2C_DATA_LO();
+ _delay_us(I2C_DELAY);
+
+ I2C_CLOCK_LO();
+ _delay_us(I2C_DELAY);
+}
+
+// Send a STOP Condition
+//
+void I2C_Stop(void)
+{
+ I2C_CLOCK_HI();
+ _delay_us(I2C_DELAY);
+
+ I2C_DATA_HI();
+ _delay_us(I2C_DELAY);
+}
+
+// write a byte to the I2C slave device
+//
+unsigned char I2C_Write(unsigned char c)
+{
+ for (char i = 0; i < 8; i++)
+ {
+ I2C_WriteBit(c & 128);
+
+ c <<= 1;
+ }
+
+
+ I2C_WriteBit(0);
+ _delay_us(I2C_DELAY);
+ _delay_us(I2C_DELAY);
+
+ // _delay_us(I2C_DELAY);
+ //return I2C_ReadBit();
+ return 0;
+}
+
+
+#endif
+
// Setleds for standard RGB
-void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds)
+void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds)
{
// ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF));
}
-void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask)
+void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask)
{
// ws2812_DDRREG |= pinmask; // Enable DDR
// new universal format (DDR)
@@ -34,14 +159,41 @@ void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pin
}
// Setleds for SK6812RGBW
-void inline ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds)
+void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds)
{
+
+ #ifdef RGBW_BB_TWI
+ uint8_t sreg_prev, twcr_prev;
+ sreg_prev=SREG;
+ twcr_prev=TWCR;
+ cli();
+ TWCR &= ~(1<<TWEN);
+ I2C_Init();
+ I2C_Start();
+ I2C_Write(0x84);
+ uint16_t datlen = leds<<2;
+ uint8_t curbyte;
+ uint8_t * data = (uint8_t*)ledarray;
+ while (datlen--) {
+ curbyte=*data++;
+ I2C_Write(curbyte);
+ }
+ I2C_Stop();
+ SREG=sreg_prev;
+ TWCR=twcr_prev;
+ #endif
+
+
// ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
// new universal format (DDR)
_SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF);
ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF));
- _delay_us(80);
+
+
+ #ifndef RGBW_BB_TWI
+ _delay_us(80);
+ #endif
}
void 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)
cli();
while (datlen--) {
- curbyte=*data++;
+ curbyte=(*data++);
asm volatile(
" ldi %0,8 \n\t"