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

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sbDriver.cpp Source File

sbDriver.cpp

00001 //Low level driver for shiftbrite modules
00002 #include <iostream>
00003 #include "mbed.h"
00004 #include "sbDriver.h"
00005 
00006 //#define ERRORPRINT //Comment out to not see any error message on STD::
00007 
00008 
00009 //NOTES ON THE SHIFTBRITE MODULES
00010 /*
00011  The modules are daisy chained and they buffer data, clock, latch and enable signals from in to out.
00012  Imagine the chain of leds as a VERY long shift register, growing by 32 bits (4 bytes) for each LED. 
00013  Each LED is 10 bits and the complete RGB set is
00014 Bit #31                                 #0
00015       00010101  01010101 01010101 01010101
00016  (msb)xC\--LED1----/\--LED2---/\--LED3---/(lsb)
00017           BLUE         GREEN      RED
00018  Two most msb bits are not used except to enter COMMAND mode by setting bit 30
00019  In COMMAND mode set a value of 0 to 127 for each led that adjust the max current from 30% to 100%
00020  Manual recommends red120, green100 and blue100.
00021  
00022  Data is moved out startgin with MSB.
00023  Data is latched into the *WHOLE* chain with a *SINGLE* latch pulse.
00024  I.E, if you have 2 leds you clock in 64 bits followed by *one* latch pulse
00025  The first 32 bits will be latched into the LED on the very end of the chain. 
00026  Thus the last 32 bit will be latched into the LED closest to the MCU.
00027  
00028  There is no RESET command for the A6281's. They are only reset at power up.
00029  Thus, if they loose synchronization with the clock/data you have to cycle the power.
00030  I have a FET/Transisor circuit that allows me to do this using the reset() member function
00031  
00032  There needs to be a delay from the last bit to the positive edge of the latch pulse (see datasheet).
00033  
00034  */
00035  
00036  
00037 //=============================================================================================    
00038 // colour class to hold a led colour value
00039 colour colour::operator=(unsigned short int v){
00040     setColour(v); // this will also range check
00041     return *this;
00042 }
00043 //--------------------
00044 
00045 colour colour::operator=(colour c){
00046     value = c.value;
00047     return *this;
00048 }
00049 
00050 
00051 //=============================================================================================    
00052 //rgbLed class to manupilate RGB colours as one object
00053 
00054 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
00055     setRgbLed(rgbValue); // this way all the other house keeping chores will be done
00056 }
00057 //--------------------
00058 rgbLed::rgbLed(unsigned short int red, unsigned short int green, unsigned short int blue){ //overload for  seperate r,g,b arguments. Remember to updatepacket
00059     this->red=red;
00060     this->green = green;
00061     this->blue = blue;
00062 }
00063 //--------------------
00064 
00065 rgbLed::rgbLed(){//no arguments given so default to 0
00066     //red.setColour(0); //red is an colour object, not just a value
00067     red=0;//use overloaded operator
00068     //green.setColour(0);
00069     green = 0;
00070     //blue.setColour(0);
00071     blue = 0;
00072     //packet = 0; 
00073     
00074 }
00075 //--------------------
00076 unsigned long int rgbLed::getPacket(){
00077     //Convert R, G and B values into one 4 byte packet ready for trnsmittion to SB
00078     //TO DO : Confirm that unsigned long int is 4 bytes long.......
00079     //NOTE, This compensates for SB being GRB and nor RGB
00080     unsigned long int temp;
00081     temp = 0; // initialize - DATA MODE
00082     //temp = 0x01; //init - COMMAND MODE
00083     temp <<=2; //shift in mode
00084     temp |= (blue.getColour()& 0X3FF);
00085     //ser_p->printf("BLUE: 0x%lx",temp);
00086     temp <<= 10;
00087     temp |= (red.getColour() & 0X3FF);
00088     temp <<=10;
00089     temp |= (green.getColour() & 0X3FF);
00090     return temp;
00091 }
00092 //--------------------
00093 
00094 void rgbLed::setRgbLed(unsigned long int rgbValue){ // RGB value e.g. 0xFFFFFF. Will expand 0XFF to 0x3FF as per colour range
00095 // THIS IS NOT THE BEST AS IT WILL EXPAND
00096 // First, pull each colour out and set accordingly in rgbLed
00097     blue.setColour(4*((unsigned short int)(rgbValue & 0X0000FF)));//blue
00098     //But, remember, the range is 0-0x3FF, not 0-0xFF
00099     green = 4*((unsigned short int)((rgbValue >> 8) & 0X0000FF));//This uses the overloaded = operator
00100     red = 4*((unsigned short int)((rgbValue >> 16) & 0X0000FF));
00101 }
00102 //--------------------
00103 
00104 void rgbLed::setRgbLed(unsigned short int red, unsigned short int green, unsigned short int blue){ //overload for  seperate r,g,b arguments
00105 //THIS IS THE BEST WAY AS YOU CAN SPECIFY THE FULL 0-0X3FF RANGE
00106     this->red=red;//This should kick in the operator overloaded f() and do a range check
00107     this->green = green;
00108     this->blue = blue;
00109 }
00110 
00111 
00112 
00113 //=============================================================================================
00114 // Display object tracking/controlling multiple rgbLed objects    
00115 //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
00116 shiftBriteDisplay::shiftBriteDisplay (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
00117 // OK, so the sb control/data lines have been setup via references
00118 //Allocate memory for moduleCount* sb modules
00119     //serial_p = port;
00120     spi.format(8,0);//8 bit, mode 0
00121     spi.frequency(100000);//100kHz clk
00122 
00123 
00124     this->moduleCount = moduleCount;
00125     module_p = new rgbLed[moduleCount];//
00126     if(!module_p){
00127         //to do : WHAT TO DO WITH ERRORS?
00128 #ifdef ERRORPRINT
00129         serial_p->printf("Unable to allocate memory for RGB led array\r\n");
00130 #endif
00131         while(1);// for now just get stuck here
00132     }
00133     
00134     priv_reset(); //assuming cct connected, remove power for a short time to reset the chips
00135     priv_SBEnable();
00136     
00137     setCurrentCorr(0x78,0x64,0x64);//setup default rgb values
00138     f_update = 0;
00139 }
00140 //--------------------
00141 
00142 void shiftBriteDisplay::setCurrentCorr(unsigned short int red, unsigned short int green, unsigned short int blue){
00143         //Now, for each module, set a command packet with
00144         //appropriately loaded current control values
00145         //and send
00146         //Uses same module_p as normal operations
00147         //This saves and restores the current colour values
00148         unsigned short int i, r,g,b;//storage for temporary colour memory
00149         
00150         //save user selected value for current correction reg values with some range checking
00151         rCorr = red & 0X7F; // ensure that it is no larger than 0x7F
00152         gCorr = green & 0x7F;
00153         bCorr= blue & 0x7F;
00154         
00155         if(f_update == 0){
00156         f_update=1; //prevent the ISR from messing this up
00157         //Backup the colours
00158         
00159         //do it
00160         //As per recommenation, set red=120, green and blue = 100
00161         for(i=0; i != moduleCount; i++){
00162             r=module_p[i].getRed();
00163             g=module_p[i].getGreen();
00164             b=module_p[i].getBlue();
00165             setLed(i,red,green,blue);
00166             send(module_p[i],1);
00167             setLed(i,r,g,b); //restore colours
00168         }
00169  /*       for(i=0; i != moduleCount; i++){
00170             send(module_p[i],1);
00171         }*/
00172         priv_SBLatch();
00173         f_update=0;
00174 #ifdef ERRORPRINT
00175         } 
00176         else {
00177             serial_p->printf("Current adj packet lost\r\n");
00178 #endif
00179         }
00180 
00181 }
00182 
00183 //Overloaded member f()
00184 void shiftBriteDisplay::setCurrentCorr(){
00185     setCurrentCorr(rCorr,gCorr,bCorr); // call the setter with the correct values
00186 }
00187 //--------------------
00188 
00189 shiftBriteDisplay::~shiftBriteDisplay(){//Destructor
00190     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
00191 }
00192 //--------------------
00193 
00194 void shiftBriteDisplay::setLed(unsigned int moduleNum, unsigned long int rgbValue){
00195     //Set the colour of a specific LED in the array
00196     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);
00197     }
00198 //--------------------
00199 void shiftBriteDisplay::setLed(unsigned int moduleNum, unsigned short int red, unsigned short int green, unsigned short int blue){
00200     module_p[moduleNum].setRgbLed(red,green,blue);
00201 }  
00202 //--------------------
00203 
00204 void shiftBriteDisplay::send(rgbLed M, unsigned short int commandStatus){
00205     unsigned long int temp;
00206     unsigned char byt;
00207     temp = M.getPacket();//Will pull in the 4 bytes of RGB data
00208     //Now, massage the hardware to send the data bits for this particular led module
00209     //Remember, spi writes 8 bits at a time so I need to access the packet a byte at a time
00210     //but I also need to start at the MSB
00211     byt = (unsigned char)( 0X000000FF & (temp >> 24));//msb
00212     if(commandStatus == 1){//i.e. adjust current control registers
00213         byt |= 0x40;//Add in the control flag to tell the shift Brite LED module that we are talking to the control registers
00214     }
00215     spi.write(byt);
00216     byt = (unsigned char)( 0X000000FF & (temp >> 16));
00217     spi.write(byt);
00218     byt = (unsigned char)( 0X000000FF & (temp >> 8));
00219     spi.write(byt);
00220     byt = (unsigned char)( 0X000000FF & temp);
00221     spi.write(byt);
00222 }
00223 
00224 //--------------------
00225 
00226 void shiftBriteDisplay::priv_reset(){
00227         sb_reset=0;
00228         wait(0.1);
00229         sb_reset=1;
00230         /*TO DO - init SB current control registers ? */
00231         wait(0.1); //allow power to settle
00232 }
00233 
00234 //--------------------
00235 
00236 void shiftBriteDisplay::displayFrame(){
00237 unsigned int i;
00238     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
00239         f_update = 1;
00240         //TO DO - do any harware init e.g., reset the whole chain or enable the display or whatever
00241         for(i=0; i != moduleCount; i++){
00242          //do something with module_p[i]
00243             send(module_p[i]); // transmit the rgb info of this led to the chain
00244         }
00245         //Complete the hardware handshaking etc
00246         priv_SBLatch(); // Latch the complete string of LED data, i.e. the frame
00247         f_update = 0;
00248         
00249         setCurrentCorr();//force a reload of the current correction register values
00250         
00251     }else {
00252        //Do nothing if we are alreay in an update cycle. In fact, for now, destructively chuck the update away.
00253 #ifdef ERRORPRINT
00254         serial_p->printf("Data Packet Lost\r\n");
00255 #endif
00256     }
00257 }
00258 
00259 void shiftBriteDisplay::rotateLeft(){
00260      rgbLed temp; //temporary object to hold data
00261     unsigned int i;
00262         temp.setRgbLed(module_p[0].getRed(),module_p[0].getGreen(),module_p[0].getBlue());
00263         for(i=0; i != moduleCount-1; i++){
00264             setLed(i,module_p[i+1].getRed(),module_p[i+1].getGreen(),module_p[i+1].getBlue());
00265         }
00266         setLed(moduleCount-1,temp.getRed(),temp.getGreen(),temp.getBlue());   
00267 }
00268 
00269 void shiftBriteDisplay::shiftLeft(unsigned short int inR,unsigned short int inG,unsigned short int inB){;//info shifted out is lost, 
00270     unsigned int i;
00271         for(i=0; i != moduleCount-1; i++){
00272             setLed(i,module_p[i+1].getRed(),module_p[i+1].getGreen(),module_p[i+1].getBlue());
00273         }
00274         if(inR==0 && inG==0 && inB==0)
00275         setLed(moduleCount-1,0,0,0);
00276         else
00277         setLed(moduleCount-1,inR,inG,inB);        
00278 }
00279 
00280 void shiftBriteDisplay::rotateRight(){;
00281      rgbLed temp; //temporary object to hold data
00282     unsigned int i;
00283         temp.setRgbLed(module_p[moduleCount-1].getRed(),module_p[moduleCount-1].getGreen(),module_p[moduleCount-1].getBlue());
00284         for(i=moduleCount; i != 0; i--){
00285             setLed(i-1,module_p[i-2].getRed(),module_p[i-2].getGreen(),module_p[i-2].getBlue());
00286         }
00287         setLed(0,temp.getRed(),temp.getGreen(),temp.getBlue());   
00288 }
00289 void shiftBriteDisplay::shiftRight(unsigned short int inR,unsigned short int inG,unsigned short int inB){;//info shifted out is lost
00290     unsigned int i;
00291         for(i=moduleCount; i != 0; i--){
00292             setLed(i-1,module_p[i-2].getRed(),module_p[i-2].getGreen(),module_p[i-2].getBlue());
00293         }
00294         if(inR==0 && inG==0 && inB==0)
00295         setLed(0,0,0,0);
00296         else
00297         setLed(0,inR,inG,inB);   
00298 }
00299 void shiftBriteDisplay::turnOn(){;
00300     priv_SBEnable();
00301 }
00302 void shiftBriteDisplay::turnOff(){;
00303     priv_SBDisable();
00304 }
00305 
00306 void shiftBriteDisplay::flip(){; //swop positions
00307     rgbLed temp; //temporary object to hold data
00308     unsigned int i;
00309     for(i=0; i != moduleCount/2; i++){
00310         temp.setRgbLed(module_p[i].getRed(),module_p[i].getGreen(),module_p[i].getBlue());
00311         setLed(i,module_p[moduleCount-1-i].getRed(),module_p[moduleCount-1-i].getGreen(),module_p[moduleCount-1-i].getBlue());
00312         setLed(moduleCount-i-1,temp.getRed(),temp.getGreen(),temp.getBlue());        
00313     }
00314 }
00315 
00316 void shiftBriteDisplay::invert(){; //invert colours
00317     unsigned int i;
00318     for(i=0; i != moduleCount; i++){
00319         //module_p[i].getRed();
00320         setLed(i,1023-module_p[i].getRed(),1023-module_p[i].getGreen(),1023-module_p[i].getBlue());
00321     }
00322 }
00323 
00324 //=============================================================================================