Johan Kritzinger
/
FRDMKL25Z-ShiftBrite
A few classes to interface one or more ShiftBrite module to the FRDM KL25Z.
Embed:
(wiki syntax)
Show/hide line numbers
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 //=============================================================================================
Generated on Thu Jul 14 2022 13:46:59 by 1.7.2