diff options
Diffstat (limited to 'quantum/light_ws2812.c')
| -rwxr-xr-x | quantum/light_ws2812.c | 151 | 
1 files changed, 146 insertions, 5 deletions
| diff --git a/quantum/light_ws2812.c b/quantum/light_ws2812.c index 401845e855..a883b13884 100755 --- a/quantum/light_ws2812.c +++ b/quantum/light_ws2812.c @@ -16,14 +16,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() +{ +    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() +{ +    // 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() +{ +    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 +148,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 +264,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" | 
