// ---- COMPROBACIONES DE COMPATIBILIDAD ----
#IF getenv("VERSION")<5.019
//test realizado con compilador CCS v5.019
//para versiones anteriores comprobar que el codigo
//generado se adecua a los tiempos requeridos
#ERROR Compilador antiguo
#ENDIF
#IF getenv("CLOCK") != 32000000
//necesitamos que el PIC corra a 32MHZ al menos
#ERROR Velocidad del PIC muy baja
#ENDIF
#IFNDEF NUM_LEDS
#ERROR "NUM_LEDS" no definido
#ELSE
#IF NUM_LEDS > 85
//solo podemos usar un maximo de 85 leds.
//Cada led usa 3 bytes, y nuestro contador de envio es un int
#ERROR "NUM_LEDS" tiene que ser menor a 85
#ELIF NUM_LEDS*3 > getenv("RAM")
#ERROR Tu PIC no tiene suficiente RAM para tantos LEDs
#ENDIF
#ENDIF
// ------------------------------------------
#include <stdlibm.h>
#byte INDF0 = getenv("SFR:INDF0")
#byte FSR0L = getenv("SFR:FSR0L")
#byte FSR0H = getenv("SFR:FSR0H")
#bit GIE = getenv("BIT:GIE")
int *pixels; //puntero al la primera direccion donde se guardan los valores
int brightness = 0; //permite ajustar el brillo sin modificar el color
int numLEDs = 0; //cantidad de leds en la tira
int numBytes = 0; //numero de bytes usados
void ConfigPixels(int n){
//n = numero de leds en la tira
numLeds = n; //establece la cantidad de leds a usar
numBytes = n * 3; //cantidad de bytes necesarios para manejar a todos los leds
pixels
= malloc(numBytes
); //crea espacio en memoria para los leds que vamos a usar
if(pixels){
}
}
int NumPixels(void){
return numLeds;
}
void SetPixelColor(int n, int r, int g, int b){
//Set pixel color from separate R,G,B components:
if(n < numLEDs) {
if(brightness) { // See notes in setBrightness()
r = (r * brightness) >> 8;
g = (g * brightness) >> 8;
b = (b * brightness) >> 8;
}
int * p = &pixels[n * 3];
*p++ = r;
*p++ = g;
*p = b;
}
}
void SetPixelColor(int n, int32 c){
//Set pixel color from 'packed' 32-bit RGB color:
if(n < numLEDs) {
int r = (int)(c >> 16);
int g = (int)(c >> 8);
int b = (int)c;
if(brightness) { // See notes in setBrightness()
r = (r * brightness) >> 8;
g = (g * brightness) >> 8;
b = (b * brightness) >> 8;
}
int * p = &pixels[n * 3];
*p++ = r;
*p++ = g;
*p = b;
}
}
int32 Color32(int r, int g, int b){
//Convierte los colores separados R,G,B en un paquete de 32 bits con el color
return ((int32)r << 16) | ((int32)g << 8) | b;
}
int32 GetPixelColor(int n){
//devuelve el color de un pixel que hayamos "coloreado" antes
//en formato de 32bits y en order RGB
if(n < numLEDs) {
long ofs = n * 3;
return (int32)((pixels[ofs] << 16) | (pixels[ofs + 1] << 8) | pixels[ofs + 2]);
}
return 0; // Pixel # is out of bounds
}
void SetBrightness(int b) {
// Adjust output brightness; 0=darkest (off), 255=brightest. This does
// NOT immediately affect what's currently displayed on the LEDs. The
// next call to show() will refresh the LEDs at this level. However,
// this process is potentially "lossy," especially when increasing
// brightness. The tight timing in the WS2811/WS2812 code means there
// aren't enough free cycles to perform this scaling on the fly as data
// is issued. So we make a pass through the existing color data in RAM
// and scale it (subsequent graphics commands also work at this
// brightness level). If there's a significant step up in brightness,
// the limited number of steps (quantization) in the old data will be
// quite visible in the re-scaled version. For a non-destructive
// change, you'll need to re-render the full strip data. C'est la vie.
// Stored brightness value is different than what's passed.
// This simplifies the actual scaling math later, allowing a fast
// 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t,
// adding 1 here may (intentionally) roll over...so 0 = max brightness
// (color values are interpreted literally; no scaling), 1 = min
// brightness (off), 255 = just below max brightness.
int newBrightness = b + 1;
if(newBrightness != brightness) { // Compare against prior value
// Brightness has changed -- re-scale existing data in RAM
int c;
int *ptr = pixels;
int oldBrightness = brightness - 1; // De-wrap old brightness value
long scale;
if(oldBrightness == 0)
scale = 0; // Avoid /0
else if
(b == 255) scale = 65535 / oldBrightness;
else
scale = (((long)newBrightness << 8) - 1) / oldBrightness;
for(int i=0; i<numBytes; i++) {
c = *ptr;
*ptr++ = (c * scale) >> 8;
}
brightness = newBrightness;
}
}
void ShowPixels(void){
short GIEval;
int i; //loop
GIEVal = GIE; //guardo valor de global interrupt enable
GIE = 0; //deshabilito interrupciones
i = numBytes; //numero de bytes a enviar
//apunto FSR0 al inicio de mis bytes
FSR0L = pixels;
FSR0H = pixels >> 8;
//10 instrucciones por cada bit: HHxxxxxLLL
//OUT instructions: ^ ^ ^ (T=0,2,7)
SendByte: //Clk Instr
//bit7 ---
DAT = TRUE; //0 1
if(!bit_test(INDF0, 7)) //1 1
DAT = FALSE; //2 1
delay_cycles(4); //3-6 4
DAT = FALSE; //7 1
delay_cycles(2); //8-9 2
//bit6 ---
DAT = TRUE; //0 1
if(!bit_test(INDF0, 6)) //1 1
DAT = FALSE; //2 1
delay_cycles(4); //3-6 4
DAT = FALSE; //7 1
delay_cycles(2); //8-9 2
//bit5 ---
DAT = TRUE; //0 1
if(!bit_test(INDF0, 5)) //1 1
DAT = FALSE; //2 1
delay_cycles(4); //3-6 4
DAT = FALSE; //7 1
delay_cycles(2); //8-9 2
//bit4 ---
DAT = TRUE; //0 1
if(!bit_test(INDF0, 4)) //1 1
DAT = FALSE; //2 1
delay_cycles(4); //3-6 4
DAT = FALSE; //7 1
delay_cycles(2); //8-9 2
//bit3 ---
DAT = TRUE; //0 1
if(!bit_test(INDF0, 3)) //1 1
DAT = FALSE; //2 1
delay_cycles(4); //3-6 4
DAT = FALSE; //7 1
delay_cycles(2); //8-9 2
//bit2 ---
DAT = TRUE; //0 1
if(!bit_test(INDF0, 2)) //1 1
DAT = FALSE; //2 1
delay_cycles(4); //3-6 4
DAT = FALSE; //7 1
delay_cycles(2); //8-9 2
//bit1 ---
DAT = TRUE; //0 1
if(!bit_test(INDF0, 1)) //1 1
DAT = FALSE; //2 1
delay_cycles(4); //3-6 4
DAT = FALSE; //7 1
delay_cycles(2); //8-9 2
//bit0 ---
DAT = TRUE; //0 1
if(!bit_test(INDF0, 0)) //1 1
DAT = FALSE; //2 1
#asm
DECFSZ i, F //3 1 decrementar contador de bytes enviados, si es cero salta 1 -> listo.
GOTO Salto //4 1 salta 1 instruccion (no me deja usar GOTO $+2 ni BRA 2 ¿?)
GOTO Listo //5 1 todo enviado. Salir
#endasm
Salto:
FSR0L++; //6 1 incremento puntero
DAT = FALSE; //7 1 PIN = LOW
goto SendByte; //8 2 vuelve al principio
Listo:
DAT = FALSE;
delay_cycles(2);
// fin de transmision
delay_us(50); //espero 50uS para volver a enviar
GIE = GIEval; //restauro valor de GIE
}