Initial import of goggles v2
[goggles] / ws2811.c
CommitLineData
5fc23db2
JM
1#include <stdint.h>
2#include <stdbool.h>
3
4#include "user.h"
5
6#include "ws2811.h"
7
8/* this holds the G R B bytes for the entire string */
9unsigned char rgbdata[RGB_COUNT];
10
11
12/* These values are placed in common memory so that they can be accessed
13 * quickly without a bank switch by the routines below, THIS IS IMPORTANT,
14 * it will not run properly without it */
15volatile uint8_t rgb_sample @ 0x7B;
16volatile uint8_t rgb_byte @ 0x7C;
17volatile uint8_t rgb_bit @ 0x7D;
18
19// send the whole pile of data
20static void ws2811_send(void)
21{
22#asm
23 // copy the led colour array location into FSR0 for fast access
24 MOVLW HIGH _rgbdata
25 MOVWF FSR0H
26 MOVLW LOW _rgbdata
27 MOVWF FSR0L
28
29 // load next byte from array into working reg
30ws2811_nextbyte:
31 MOVIW FSR0++
32 MOVWF _rgb_sample
33 MOVLW 8 // reset bit count
34 MOVWF _rgb_bit
35
36ws2811_sendbit:
37 // you assume its a zero then test if its one
38// MOVLW 0xC0 ;11000000B
39 MOVLW 0x80 ;10000000B
40
41 RLF _rgb_sample,f
42 BTFSC STATUS,0 // CARRY
43 //asm("MOVLW 0xF8 "); // 11111000B
44 MOVLW 0xF0 // 11110000B
45
46 BANKSEL (SSP1BUF)
47 MOVWF BANKMASK(SSP1BUF)
48
49 // any more bits
50 DECFSZ _rgb_bit,f
51 BRA ws2811_delay
52
53 // any more bytes
54 DECFSZ _rgb_byte,f
55 BRA ws2811_nextbyte
56 BRA ws2811_end
57
58ws2811_delay:
59 NOP
60 NOP
61 NOP
62 BRA ws2811_sendbit
63
64ws2811_end:
65
66
67#endasm
68
69 // all done
70}
71
72#if _XTAL_FREQ != 32000000L
73#error "This code requires 32MHz system clock or above"
74#endif
75
76void ws2811_init(void)
77{
78 // SPI is on RA0
79 TRISAbits.TRISA0 = 0; // SDO is RA0
80 ANSELAbits.ANSA0 = 0; // not analog
81
82 // SCK (SPI Clock) is RA1
83 // SDI (SPI In) is RA2
84 APFCONbits.SDOSEL = 0; // use RA0 not RA4 for output
85
86 // at 8MHz Tclk 0 = 2 bits, 1 = 6 bits.
87 // write to SSP1BUF
88 SSP1CON1bits.SSPM = 0b0000; // SPI Master Fosc/4
89 SSP1CON1bits.SSPEN = 1; // enable MSSP
90}
91
92void ws2811_transmit(void)
93{
94 rgb_byte = RGB_COUNT;
95 ws2811_send(); // send the first bit
96}