A few classes to interface one or more ShiftBrite module to the FRDM KL25Z.

Dependencies:   mbed

Committer:
JoKer
Date:
Tue Aug 19 07:09:20 2014 +0000
Revision:
0:f76850de7b57
Child:
3:9376bf1f1bbd
Working version of shiftBrite classes. V1.0 - 19/8/2014

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JoKer 0:f76850de7b57 1 //Low level driver for shiftbrite modules
JoKer 0:f76850de7b57 2 #include <iostream>
JoKer 0:f76850de7b57 3 #include "mbed.h"
JoKer 0:f76850de7b57 4 #include "sbDriver.h"
JoKer 0:f76850de7b57 5
JoKer 0:f76850de7b57 6 //#define DEBUGPRINT //Uncoment to see various debug output
JoKer 0:f76850de7b57 7
JoKer 0:f76850de7b57 8 //#define SENDPRINT //Uncomment to see what is being sent to the SB's
JoKer 0:f76850de7b57 9
JoKer 0:f76850de7b57 10 #define ERRORPRINT //Comment to not see any error message on STD::
JoKer 0:f76850de7b57 11
JoKer 0:f76850de7b57 12
JoKer 0:f76850de7b57 13 //NOTES ON THE SHIFTBRITE MODULES
JoKer 0:f76850de7b57 14 /*
JoKer 0:f76850de7b57 15 The modules are daisy chained and they buffer data, clock, latch and enable signals from in to out.
JoKer 0:f76850de7b57 16 Imagine the chain of leds as a VERY long shift register, growing by 32 bits (4 bytes) for each LED.
JoKer 0:f76850de7b57 17 Each LED is 10 bits and the complete RGB set is
JoKer 0:f76850de7b57 18 Bit #31 #0
JoKer 0:f76850de7b57 19 00010101 01010101 01010101 01010101
JoKer 0:f76850de7b57 20 (msb)xC\--LED1----/\--LED2---/\--LED3---/(lsb)
JoKer 0:f76850de7b57 21 BLUE GREEN RED
JoKer 0:f76850de7b57 22 Two most msb bits are not used except to enter COMMAND mode by setting bit 30
JoKer 0:f76850de7b57 23 In COMMAND mode set a value of 0 to 127 for each led that adjust the max current from 30% to 100%
JoKer 0:f76850de7b57 24 Manual recommends red120, green100 and blue100.
JoKer 0:f76850de7b57 25
JoKer 0:f76850de7b57 26 Data is moved out startgin with MSB.
JoKer 0:f76850de7b57 27 Data is latched into the *WHOLE* chain with a *SINGLE* latch pulse.
JoKer 0:f76850de7b57 28 I.E, if you have 2 leds you clock in 64 bits followed by *one* latch pulse
JoKer 0:f76850de7b57 29 The first 32 bits will be latched into the LED on the very end of the chain.
JoKer 0:f76850de7b57 30 Thus the last 32 bit will be latched into the LED closest to the MCU.
JoKer 0:f76850de7b57 31
JoKer 0:f76850de7b57 32 There is no RESET command for the A6281's. They are only reset at power up.
JoKer 0:f76850de7b57 33 Thus, if they loose synchronization with the clock/data you have to cycle the power.
JoKer 0:f76850de7b57 34 I have a FET/Transisor circuit that allows me to do this using the reset() member function
JoKer 0:f76850de7b57 35
JoKer 0:f76850de7b57 36 There needs to be a delay from the last bit to the positive edge of the latch pulse (see datasheet).
JoKer 0:f76850de7b57 37
JoKer 0:f76850de7b57 38 */
JoKer 0:f76850de7b57 39
JoKer 0:f76850de7b57 40
JoKer 0:f76850de7b57 41 //=============================================================================================
JoKer 0:f76850de7b57 42 // colour class to hold a led colour value
JoKer 0:f76850de7b57 43 colour colour::operator=(unsigned short int v){
JoKer 0:f76850de7b57 44 setColour(v); // this will also range check
JoKer 0:f76850de7b57 45 return *this;
JoKer 0:f76850de7b57 46 }
JoKer 0:f76850de7b57 47 //--------------------
JoKer 0:f76850de7b57 48
JoKer 0:f76850de7b57 49 colour colour::operator=(colour c){
JoKer 0:f76850de7b57 50 value = c.value;
JoKer 0:f76850de7b57 51 return *this;
JoKer 0:f76850de7b57 52 }
JoKer 0:f76850de7b57 53
JoKer 0:f76850de7b57 54
JoKer 0:f76850de7b57 55 //=============================================================================================
JoKer 0:f76850de7b57 56 //rgbLed class to manupilate RGB colours as one object
JoKer 0:f76850de7b57 57
JoKer 0:f76850de7b57 58 rgbLed::rgbLed(unsigned long int rgbValue){ // constructor for RGB value e.g. 0xFFFFFF. Will expand 0XFF to 0x3FF as per colour range. Remember to update packet
JoKer 0:f76850de7b57 59 setRgbLed(rgbValue); // this way all the other house keeping chores will be done
JoKer 0:f76850de7b57 60 }
JoKer 0:f76850de7b57 61 //--------------------
JoKer 0:f76850de7b57 62 rgbLed::rgbLed(unsigned short int red, unsigned short int green, unsigned short int blue){ //overload for seperate r,g,b arguments. Remember to updatepacket
JoKer 0:f76850de7b57 63 this->red=red;
JoKer 0:f76850de7b57 64 this->green = green;
JoKer 0:f76850de7b57 65 this->blue = blue;
JoKer 0:f76850de7b57 66 }
JoKer 0:f76850de7b57 67 //--------------------
JoKer 0:f76850de7b57 68
JoKer 0:f76850de7b57 69 rgbLed::rgbLed(){//no arguments given so default to 0
JoKer 0:f76850de7b57 70 //red.setColour(0); //red is an colour object, not just a value
JoKer 0:f76850de7b57 71 red=0;//use overloaded operator
JoKer 0:f76850de7b57 72 //green.setColour(0);
JoKer 0:f76850de7b57 73 green = 0;
JoKer 0:f76850de7b57 74 //blue.setColour(0);
JoKer 0:f76850de7b57 75 blue = 0;
JoKer 0:f76850de7b57 76 //packet = 0;
JoKer 0:f76850de7b57 77
JoKer 0:f76850de7b57 78 }
JoKer 0:f76850de7b57 79 //--------------------
JoKer 0:f76850de7b57 80 unsigned long int rgbLed::getPacket(){
JoKer 0:f76850de7b57 81 //Convert R, G and B values into one 4 byte packet ready for trnsmittion to SB
JoKer 0:f76850de7b57 82 //TO DO : Confirm that unsigned long int is 4 bytes long.......
JoKer 0:f76850de7b57 83 //NOTE, This compensates for SB being GRB and nor RGB
JoKer 0:f76850de7b57 84 unsigned long int temp;
JoKer 0:f76850de7b57 85 temp = 0; // initialize - DATA MODE
JoKer 0:f76850de7b57 86 //temp = 0x01; //init - COMMAND MODE
JoKer 0:f76850de7b57 87 temp <<=2; //shift in mode
JoKer 0:f76850de7b57 88 temp |= (blue.getColour()& 0X3FF);
JoKer 0:f76850de7b57 89 //ser_p->printf("BLUE: 0x%lx",temp);
JoKer 0:f76850de7b57 90 temp <<= 10;
JoKer 0:f76850de7b57 91 temp |= (red.getColour() & 0X3FF);
JoKer 0:f76850de7b57 92 temp <<=10;
JoKer 0:f76850de7b57 93 temp |= (green.getColour() & 0X3FF);
JoKer 0:f76850de7b57 94 return temp;
JoKer 0:f76850de7b57 95 }
JoKer 0:f76850de7b57 96 //--------------------
JoKer 0:f76850de7b57 97
JoKer 0:f76850de7b57 98 void rgbLed::setRgbLed(unsigned long int rgbValue){ // RGB value e.g. 0xFFFFFF. Will expand 0XFF to 0x3FF as per colour range
JoKer 0:f76850de7b57 99 // THIS IS NOT THE BEST AS IT WILL EXPAND
JoKer 0:f76850de7b57 100 // First, pull each colour out and set accordingly in rgbLed
JoKer 0:f76850de7b57 101 blue.setColour(4*((unsigned short int)(rgbValue & 0X0000FF)));//blue
JoKer 0:f76850de7b57 102 //But, remember, the range is 0-0x3FF, not 0-0xFF
JoKer 0:f76850de7b57 103 green = 4*((unsigned short int)((rgbValue >> 8) & 0X0000FF));//This uses the overloaded = operator
JoKer 0:f76850de7b57 104 red = 4*((unsigned short int)((rgbValue >> 16) & 0X0000FF));
JoKer 0:f76850de7b57 105 }
JoKer 0:f76850de7b57 106 //--------------------
JoKer 0:f76850de7b57 107
JoKer 0:f76850de7b57 108 void rgbLed::setRgbLed(unsigned short int red, unsigned short int green, unsigned short int blue){ //overload for seperate r,g,b arguments
JoKer 0:f76850de7b57 109 //THIS IS THE BEST WAY AS YOU CAN SPECIFY THE FULL 0-0X3FF RANGE
JoKer 0:f76850de7b57 110 this->red=red;//This should kick in the operator overloaded f() and do a range check
JoKer 0:f76850de7b57 111 this->green = green;
JoKer 0:f76850de7b57 112 this->blue = blue;
JoKer 0:f76850de7b57 113 }
JoKer 0:f76850de7b57 114
JoKer 0:f76850de7b57 115
JoKer 0:f76850de7b57 116
JoKer 0:f76850de7b57 117 //=============================================================================================
JoKer 0:f76850de7b57 118 // Display object tracking/controlling multiple rgbLed objects
JoKer 0:f76850de7b57 119 shiftBriteDisplay::shiftBriteDisplay (Serial *port,DigitalOut &latch, DigitalOut &enable, DigitalOut &reset, SPI &spiPort, unsigned int moduleCount):/*PC(port),*/sb_latch(latch), sb_enable(enable), sb_reset(reset), spi(spiPort){ //constructor
JoKer 0:f76850de7b57 120 // OK, so the sb control/data lines have been setup via references
JoKer 0:f76850de7b57 121 //Allocate memory for moduleCount* sb modules
JoKer 0:f76850de7b57 122 serial_p = port;
JoKer 0:f76850de7b57 123 #ifdef DEBUGPRINT
JoKer 0:f76850de7b57 124 serial_p->printf("Construct shiftBriteDisplay\r\n");
JoKer 0:f76850de7b57 125 #endif
JoKer 0:f76850de7b57 126 spi.format(8,0);//8 bit, mode 0
JoKer 0:f76850de7b57 127 spi.frequency(100000);//100kHz clk
JoKer 0:f76850de7b57 128
JoKer 0:f76850de7b57 129
JoKer 0:f76850de7b57 130 this->moduleCount = moduleCount;
JoKer 0:f76850de7b57 131 module_p = new rgbLed[moduleCount];//
JoKer 0:f76850de7b57 132 if(!module_p){
JoKer 0:f76850de7b57 133 //to do : WHAT TO DO WITH ERRORS?
JoKer 0:f76850de7b57 134 #ifdef ERRORPRINT
JoKer 0:f76850de7b57 135 serial_p->printf("Unable to allocate memory for RGB led array\r\n");
JoKer 0:f76850de7b57 136 #endif
JoKer 0:f76850de7b57 137 while(1);// for now just get stuck here
JoKer 0:f76850de7b57 138 }
JoKer 0:f76850de7b57 139
JoKer 0:f76850de7b57 140 priv_reset(); //assuming cct connected, remove power for a short time to reset the chips
JoKer 0:f76850de7b57 141 priv_SBEnable();
JoKer 0:f76850de7b57 142
JoKer 0:f76850de7b57 143 setCurrentCorr(0x78,0x64,0x64);//setup default rgb values
JoKer 0:f76850de7b57 144 f_update = 0;
JoKer 0:f76850de7b57 145 }
JoKer 0:f76850de7b57 146 //--------------------
JoKer 0:f76850de7b57 147
JoKer 0:f76850de7b57 148 void shiftBriteDisplay::setCurrentCorr(unsigned short int red, unsigned short int green, unsigned short int blue){
JoKer 0:f76850de7b57 149 //Now, for each module, set a command packet with
JoKer 0:f76850de7b57 150 //appropriately loaded current control values
JoKer 0:f76850de7b57 151 //and send
JoKer 0:f76850de7b57 152 //Uses same module_p as normal operations
JoKer 0:f76850de7b57 153 //This saves and restores the current colour values
JoKer 0:f76850de7b57 154 unsigned short int i, r,g,b;//storage for temporary colour memory
JoKer 0:f76850de7b57 155
JoKer 0:f76850de7b57 156 //save user selected value for current correction reg values with some range checking
JoKer 0:f76850de7b57 157 rCorr = red & 0X7F; // ensure that it is no larger than 0x7F
JoKer 0:f76850de7b57 158 gCorr = green & 0x7F;
JoKer 0:f76850de7b57 159 bCorr= blue & 0x7F;
JoKer 0:f76850de7b57 160
JoKer 0:f76850de7b57 161 if(f_update == 0){
JoKer 0:f76850de7b57 162 #ifdef DEBUGPRINT
JoKer 0:f76850de7b57 163 serial_p->printf("Current adj\r\n");
JoKer 0:f76850de7b57 164 #endif
JoKer 0:f76850de7b57 165 f_update=1; //prevent the ISR from messing this up
JoKer 0:f76850de7b57 166 //Backup the colours
JoKer 0:f76850de7b57 167
JoKer 0:f76850de7b57 168 //do it
JoKer 0:f76850de7b57 169 //As per recommenation, set red=120, green and blue = 100
JoKer 0:f76850de7b57 170 for(i=0; i != moduleCount; i++){
JoKer 0:f76850de7b57 171 r=module_p[i].getRed();
JoKer 0:f76850de7b57 172 g=module_p[i].getGreen();
JoKer 0:f76850de7b57 173 b=module_p[i].getBlue();
JoKer 0:f76850de7b57 174 setLed(i,red,green,blue);
JoKer 0:f76850de7b57 175 send(module_p[i],1);
JoKer 0:f76850de7b57 176 setLed(i,r,g,b); //restore colours
JoKer 0:f76850de7b57 177 }
JoKer 0:f76850de7b57 178 /* for(i=0; i != moduleCount; i++){
JoKer 0:f76850de7b57 179 send(module_p[i],1);
JoKer 0:f76850de7b57 180 }*/
JoKer 0:f76850de7b57 181 priv_SBLatch();
JoKer 0:f76850de7b57 182 f_update=0;
JoKer 0:f76850de7b57 183 #ifdef ERRORPRINT
JoKer 0:f76850de7b57 184 }
JoKer 0:f76850de7b57 185 else {
JoKer 0:f76850de7b57 186 serial_p->printf("Current adj packet lost\r\n");
JoKer 0:f76850de7b57 187 #endif
JoKer 0:f76850de7b57 188 }
JoKer 0:f76850de7b57 189
JoKer 0:f76850de7b57 190 }
JoKer 0:f76850de7b57 191
JoKer 0:f76850de7b57 192 //Overloaded member f()
JoKer 0:f76850de7b57 193 void shiftBriteDisplay::setCurrentCorr(){
JoKer 0:f76850de7b57 194 setCurrentCorr(rCorr,gCorr,bCorr); // call the setter with the correct values
JoKer 0:f76850de7b57 195 }
JoKer 0:f76850de7b57 196 //--------------------
JoKer 0:f76850de7b57 197
JoKer 0:f76850de7b57 198 shiftBriteDisplay::~shiftBriteDisplay(){//Destructor
JoKer 0:f76850de7b57 199 delete [] module_p;//Be nice, clean the house. Not strictly required as this should never be called as we never reach the end of the program
JoKer 0:f76850de7b57 200 }
JoKer 0:f76850de7b57 201 //--------------------
JoKer 0:f76850de7b57 202
JoKer 0:f76850de7b57 203 void shiftBriteDisplay::setLed(unsigned int moduleNum, unsigned long int rgbValue){
JoKer 0:f76850de7b57 204 //Set the colour of a specific LED in the array
JoKer 0:f76850de7b57 205 #ifdef DEBUGPRINT
JoKer 0:f76850de7b57 206 serial_p->printf("SetLed %u:%lx\r\n",moduleNum,rgbValue);
JoKer 0:f76850de7b57 207 #endif
JoKer 0:f76850de7b57 208 moduleCount >= moduleNum ? module_p[moduleNum].setRgbLed(rgbValue): /*TO DO - set some sort of error? For now, mess up the LAST moodule setting*/ module_p[moduleCount-1].setRgbLed(rgbValue);
JoKer 0:f76850de7b57 209 }
JoKer 0:f76850de7b57 210 //--------------------
JoKer 0:f76850de7b57 211 void shiftBriteDisplay::setLed(unsigned int moduleNum, unsigned short int red, unsigned short int green, unsigned short int blue){
JoKer 0:f76850de7b57 212 module_p[moduleNum].setRgbLed(red,green,blue);
JoKer 0:f76850de7b57 213 }
JoKer 0:f76850de7b57 214 //--------------------
JoKer 0:f76850de7b57 215
JoKer 0:f76850de7b57 216 void shiftBriteDisplay::send(rgbLed M, unsigned short int commandStatus){
JoKer 0:f76850de7b57 217 unsigned long int temp;
JoKer 0:f76850de7b57 218 unsigned char byt;
JoKer 0:f76850de7b57 219 temp = M.getPacket();//Will pull in the 4 bytes of RGB data
JoKer 0:f76850de7b57 220 //Now, massage the hardware to send the data bits for this particular led module
JoKer 0:f76850de7b57 221 //Remember, spi writes 8 bits at a time so I need to access the packet a byte at a time
JoKer 0:f76850de7b57 222 //but I also need to start at the MSB
JoKer 0:f76850de7b57 223 #ifdef DEBUGPRINT
JoKer 0:f76850de7b57 224 serial_p->printf("send 0x%0x\r\n",temp);
JoKer 0:f76850de7b57 225 serial_p->printf("Red: 0x%x | Grn: 0x%x | Blue: 0x%x\r\n",M.getRed(),M.getGreen(),M.getBlue());
JoKer 0:f76850de7b57 226 #endif
JoKer 0:f76850de7b57 227 byt = (unsigned char)( 0X000000FF & (temp >> 24));//msb
JoKer 0:f76850de7b57 228 if(commandStatus == 1){//i.e. adjust current control registers
JoKer 0:f76850de7b57 229 byt |= 0x40;//Add in the control flag to tell the shift Brite LED module that we are talking to the control registers
JoKer 0:f76850de7b57 230 #ifdef SENDPRINT
JoKer 0:f76850de7b57 231 serial_p->printf("C");
JoKer 0:f76850de7b57 232 } //i.e. going to write current control registers
JoKer 0:f76850de7b57 233 else {
JoKer 0:f76850de7b57 234 serial_p->printf("N");
JoKer 0:f76850de7b57 235 #endif
JoKer 0:f76850de7b57 236 }
JoKer 0:f76850de7b57 237 spi.write(byt);
JoKer 0:f76850de7b57 238 #ifdef SENDPRINT
JoKer 0:f76850de7b57 239 serial_p->printf("*0x%02x",byt);
JoKer 0:f76850de7b57 240 #endif
JoKer 0:f76850de7b57 241 byt = (unsigned char)( 0X000000FF & (temp >> 16));
JoKer 0:f76850de7b57 242 spi.write(byt);
JoKer 0:f76850de7b57 243 #ifdef SENDPRINT
JoKer 0:f76850de7b57 244 serial_p->printf("%02x",byt);
JoKer 0:f76850de7b57 245 #endif
JoKer 0:f76850de7b57 246 byt = (unsigned char)( 0X000000FF & (temp >> 8));
JoKer 0:f76850de7b57 247 spi.write(byt);
JoKer 0:f76850de7b57 248 #ifdef SENDPRINT
JoKer 0:f76850de7b57 249 serial_p->printf("%02x",byt);
JoKer 0:f76850de7b57 250 #endif
JoKer 0:f76850de7b57 251 byt = (unsigned char)( 0X000000FF & temp);
JoKer 0:f76850de7b57 252 spi.write(byt);
JoKer 0:f76850de7b57 253 #ifdef SENDPRINT
JoKer 0:f76850de7b57 254 serial_p->printf("%02x\r\n",byt);
JoKer 0:f76850de7b57 255 #endif
JoKer 0:f76850de7b57 256 }
JoKer 0:f76850de7b57 257
JoKer 0:f76850de7b57 258 //--------------------
JoKer 0:f76850de7b57 259
JoKer 0:f76850de7b57 260 void shiftBriteDisplay::priv_reset(){
JoKer 0:f76850de7b57 261 sb_reset=0;
JoKer 0:f76850de7b57 262 wait(0.1);
JoKer 0:f76850de7b57 263 sb_reset=1;
JoKer 0:f76850de7b57 264 /*TO DO - init SB current control registers ? */
JoKer 0:f76850de7b57 265 wait(0.1); //allow power to settle
JoKer 0:f76850de7b57 266 }
JoKer 0:f76850de7b57 267
JoKer 0:f76850de7b57 268 //--------------------
JoKer 0:f76850de7b57 269
JoKer 0:f76850de7b57 270 void shiftBriteDisplay::displayFrame(){
JoKer 0:f76850de7b57 271 unsigned int i;
JoKer 0:f76850de7b57 272 if(f_update == 0){//Prevents doing this if an update is already in progress. This is b/c this member f() is called by an ISR etup in main
JoKer 0:f76850de7b57 273 f_update = 1;
JoKer 0:f76850de7b57 274 //TO DO - do any harware init e.g., reset the whole chain or enable the display or whatever
JoKer 0:f76850de7b57 275 for(i=0; i != moduleCount; i++){
JoKer 0:f76850de7b57 276 //do something with module_p[i]
JoKer 0:f76850de7b57 277 send(module_p[i]); // transmit the rgb info of this led to the chain
JoKer 0:f76850de7b57 278 }
JoKer 0:f76850de7b57 279 //Complete the hardware handshaking etc
JoKer 0:f76850de7b57 280 priv_SBLatch(); // Latch the complete string of LED data, i.e. the frame
JoKer 0:f76850de7b57 281 f_update = 0;
JoKer 0:f76850de7b57 282
JoKer 0:f76850de7b57 283 setCurrentCorr();//force a reload of the current correction register values
JoKer 0:f76850de7b57 284
JoKer 0:f76850de7b57 285 }else {
JoKer 0:f76850de7b57 286 //Do nothing if we are alreay in an update cycle. In fact, for now, destructively chuck the update away.
JoKer 0:f76850de7b57 287 #ifdef ERRORPRINT
JoKer 0:f76850de7b57 288 serial_p->printf("Data Packet Lost\r\n");
JoKer 0:f76850de7b57 289 #endif
JoKer 0:f76850de7b57 290 }
JoKer 0:f76850de7b57 291 }
JoKer 0:f76850de7b57 292
JoKer 0:f76850de7b57 293 //--------------------
JoKer 0:f76850de7b57 294
JoKer 0:f76850de7b57 295
JoKer 0:f76850de7b57 296 //=============================================================================================