Grzegorz Kaczmarek
/
Max7221
Fix to have load pin working with SPI1.
Fork of Max7221 by
Revision 7:a160cb7cdd86, committed 2015-11-23
- Comitter:
- ky3orr
- Date:
- Mon Nov 23 11:28:44 2015 +0000
- Parent:
- 6:191569a26f50
- Child:
- 8:3f5901f2f813
- Commit message:
- Code refactored to have MAX7219/7221 driver only with SPI chain support.
Changed in this revision
Max7221.cpp | Show annotated file Show diff for this revision Revisions of this file |
Max7221.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/Max7221.cpp Thu Nov 19 23:58:07 2015 +0000 +++ b/Max7221.cpp Mon Nov 23 11:28:44 2015 +0000 @@ -1,230 +1,105 @@ /** * @file Max7221.cpp -* @brief This file defines the Max7221 class methods and the default values for static variables +* @brief MAX7219/7221 driver class. * -* @author Dwayne S. Dilbeck -* -* @date 8/6/2013 +* @author Grzegorz Kaczmarek +* @comment Code inspired on erlier Dwayne S. Dilbeck's work +* @date 20/11/2015 */ + #include "mbed.h" #include "Max7221.h" -///Intialize the Class static members -///Devices used per SPI bus are set to ZERO -int Max7221::maxInUseSPI = 0; -///Set the static pointers to the SPI busses to NULL -SPI *Max7221::spi=NULL; -///Set the static pointers to the load signals to NULL -DigitalOut *Max7221::cs=NULL; - -/** -* Constructor. This is the default constructor -* @author Dwayne S. Dilbeck -* @param msoi The SPI pin used as input to the device. Valid values for LPC1768 are p5 or p11 -* @param mclk The SPI pin used as clock for the device. Valid values for LPC1768 are p7 or p13 -* @param load The pin used to control load for the device. Any pin capable for DigitalOut can be used, but the same load pin must be used for -* device that share the same msoi and mclk pins -* @date 8/6/2013 -*/ -Max7221::Max7221(PinName msoi, PinName mclk, PinName load){ - ///Set this insctance to pointers to the correct static pointers - this->id=maxInUseSPI; - this->maxInUse=&maxInUseSPI; - ///If no devices have been assigned to the SPI bus it must be initialized - if (spi ==NULL) { - spi = new SPI(msoi, NC, mclk); - cs = new DigitalOut(load); - } - this->max7221_spi= spi; - this->max7221_cs = cs; +Max7221::Max7221(SPI *spi, DigitalOut *cs, unsigned int position) : + mp_spi(spi), + mp_cs(cs), + m_position(position) +{ } -/** -* This method is used to write a byte of data to a specified register for only the device defined in this class instance -* @author Dwayne S. Dilbeck -* @param reg The register to write to. -* @param data The value to be written. -* @date 8/6/2013 -*//** -* This method is used to write a byte of data to a specified register for only the device defined in this class instance -* @author Dwayne S. Dilbeck -* @param reg The register to write to. -* @param data The value to be written. -* @date 8/6/2013 -*/ -void Max7221::Write( unsigned int reg, unsigned int data) { - int c = 0; - *cs = LOW; - - ///if there are multiple devices sharing the SPI buss and they preceed the current device in the cascade Write a NOOP to them - for ( c = *maxInUse; c > this->id; c--) { - max7221_spi->write(0); // no-op - max7221_spi->write(0); // no-op +void Max7221::CsLow() +{ + if(mp_cs != NULL) { + *mp_cs = LOG_0; } - ///Write to this device registers - max7221_spi->write(reg); // specify register - max7221_spi->write(data); // put data - - ///if there are multiple devices sharing the SPI buss and they follow the current device in the cascade Write a NOOP to them - for ( c=this->id-1; c >= 1; c--) { - max7221_spi->write(0); // no-op - max7221_spi->write(0); // no-op - } - *cs = HIGH; } -/** -* This method is used to write an intial set off values to the device to prepare it for use. -* @author Dwayne S. Dilbeck -* @date 8/6/2013 -*/ -void Max7221::Setup () { - // initiation of the max 7221 - // SPI setup: 8 bits, mode 0 - max7221_spi->format(8, 0); - - // going by the datasheet, min clk is 100ns so theoretically 10MHz should work... - max7221_spi->frequency(10*MHZ); - - Write(max7219_reg_scanLimit, 0x07); ///ENABLE all 8 digits - Write(max7219_reg_decodeMode, 0xff); // Turn on Code B font decode for all digits - Write(max7219_reg_shutdown, 0x01); // Disable shutdown mode - Write(max7219_reg_displayTest, 0x00); // Disable display test - for (int e=1; e<=8; e++) { // Write blank to all digits - Write(e,0xf); +void Max7221::CsHigh() +{ + if(mp_cs != NULL) { + *mp_cs = LOG_1; } - Write(max7219_reg_intensity, 0x01 ); // Set the display intensity to a low level. - // range: 0x00 to 0x0f } -/** -* This method is used to write a byte of data to a specified register for all the devices instantiated. -* @author Dwayne S. Dilbeck -* @param reg The register to write to. -* @param data The value to be written. -* @date 8/6/2013 -*/ -void Max7221::WriteAll (unsigned int reg, unsigned int data) { - ///Write to all the devices on SPI Bus #1 first - if(cs !=NULL) { - *cs = LOW; // begin - for ( int c=1; c<= maxInUseSPI; c++) { - spi->write(reg); // specify register - spi->write(data); // put data - } - *cs = HIGH; +void Max7221::WriteRaw(unsigned int reg, unsigned int data) { + if(mp_spi != NULL) { + mp_spi->write(reg); + mp_spi->write(data); } } -/** -* This method is used to display an integer to the specified device instance. Underflow and overflow result in '-' written to all digits -* @author Dwayne S. Dilbeck -* @param value An integer value to display -* @date 8/6/2013 -*/ -void Max7221::WriteInt( int value ){ - char buffer[16]; - - ///TODO:SET UPPERBOUND AND LOWERBOUND based on NUMDIGITS - ///Check the the INT value can be displayed and convert to a string. - if (value <= UPPERBOUND && value >= LOWERBOUND) { - sprintf(buffer,"%8d",value); - } else { - sprintf(buffer,"--------"); - } - ///In case a program changed the decode mode, set it again. - Write(max7219_reg_decodeMode, 0xff); - for (int i=0;i<NUMDIGITS;i++) { - ///For each character of the string, convert the ASCII to the datacode needed by the device - switch(buffer[i]){ - case 0x2d: buffer[i]=0xa; break; - case 0x20: buffer[i]=0xf; break; - default: buffer[i]= buffer[i] & 0x0f; - } - ///Call function to write the data for each character of the srting. - Write(NUMDIGITS-i,buffer[i]); - } + +void Max7221::Write(unsigned int reg, unsigned int data) { + unsigned int i; + + CsLow(); + WriteRaw(reg, data); + if(m_position > 0) { + i = m_position; + while(i--) { + WriteRaw(max7219_reg_noop, 0x0); + } + } + CsHigh(); +} + +void Max7221::TestMode(bool mode) { + if(mode) { + Write(max7219_reg_displayTest, 0x01); + } else { + Write(max7219_reg_displayTest, 0x00); + } +} + +void Max7221::UseDigitsNo(unsigned int digits_no) { + if((digits_no > 0) && (digits_no < 9)) { + Write(max7219_reg_scanLimit, (digits_no - 1)); + } +} + +void Max7221::DecodeMode(unsigned int mode) { + Write(max7219_reg_decodeMode, mode); } -/** -* This method is used to display a floating point number to the specified device instance. -* Underflow and overflow result in '-' written to all digits. The digits after the decimal -* point are truncated to fit the display. -* @author Dwayne S. Dilbeck -* @param value A float value to display -* @date 8/6/2013 -*/ -void Max7221::WriteFloat( float value ){ - char buffer[32]; - int ptr=-1,len; - int i; - - sprintf(buffer,"%f",value); - len=strlen(buffer); - i=len-1; - while(buffer[i]==0x30) { - buffer[i]='\0'; - i--; - len--; - } - for( i =0; i<=len; i++) { - switch(buffer[i]){ - case 0x2d: buffer[i]=0xa; break; - case 0x20: buffer[i]=0xf; break; - case 0x2e: buffer[i]=buffer[i-1] | 0x80; - ptr = i-1; - break; - default: buffer[i]= buffer[i]; - } - if (ptr != -1) { - buffer[i-1]=buffer[i]; - } - } - - len=strlen(buffer); - Write(max7219_reg_decodeMode, 0xff); +void Max7221::WriteDigit(unsigned int digit_no, unsigned int value) { + if(digit_no < 8) { + Write(digit_no, value); + } +} - // If too large for display set to '-' - if(len > NUMDIGITS && (ptr==-1 || ptr>NUMDIGITS)) - for (int i=0;i<NUMDIGITS;i++) { - buffer[i]=0x0a; - } - //if number is smaller than display, fill with ' ' - if (len<=NUMDIGITS) { - for (int i=1;i<=NUMDIGITS;i++) { - if(len-i>=0) { - Write(i,buffer[len-i]); - } else { - Write(i,0xf); - } - } - } else { - //Write out the buffer, truncating the decimal digits if larger than display - for (int i=0;i<NUMDIGITS;i++) { - Write(NUMDIGITS-i,buffer[i]); - } - } +void Max7221::Intensity(unsigned int intensity) { + if(intensity > 0x0F) { + intensity = 0x0F; + } + Write(max7219_reg_intensity, intensity); } -/** -* This method is used to write an intial set off values to ALL device to prepare them for use. -* @author Dwayne S. Dilbeck -* @date 8/6/2013 -*/ -void Max7221::SetupAll () { - // initiation of the max 7219 - // SPI setup: 8 bits, mode 0 - if(spi!=NULL) { - spi->format(8, 0); - spi->frequency(10*MHZ); - } - WriteAll(max7219_reg_scanLimit, 0x07); - WriteAll(max7219_reg_decodeMode, 0xff); // using an led matrix (not digits) - WriteAll(max7219_reg_shutdown, 0x01); // not in shutdown mode - WriteAll(max7219_reg_displayTest, 0x00); // no display test - for (int e=1; e<=8; e++) { // empty registers, turn all LEDs off - WriteAll(e,0xf); +void Max7221::OperationMode(bool mode) { + if(mode) { + Write(max7219_reg_shutdown, 0x01); + } else { + Write(max7219_reg_shutdown, 0x00); } - WriteAll(max7219_reg_intensity, 0x01 & 0x0f); // the first 0x0f is the value you can set - // range: 0x00 to 0x0f } +void Max7221::Setup () { + unsigned int i; + + TestMode(false); // Disable display test + UseDigitsNo(8); // Use all 8 digits + DecodeMode(0xFF); // Turn on Code B font decode for all digits + for(i=1;i<9;i++) { // Clean all digits + WriteDigit(i, 0x0F); + } + Intensity(0x01); // Set lowest display intensity(0x00-0xFF) + OperationMode(true); // Enable operation mode +}
--- a/Max7221.h Thu Nov 19 23:58:07 2015 +0000 +++ b/Max7221.h Mon Nov 23 11:28:44 2015 +0000 @@ -1,179 +1,108 @@ /** * @file Max7221.h -* @brief This file contains the class defnition of Max7221 and define statements related to the class, and max7221 device -* The methods in this class are derived from posts on the mbed forum written by Igor Skochinsky on October 2009 +* @brief Header file for the MAX7219/7221 driver class. * -* @author Dwayne S. Dilbeck -* -* @date 8/6/2013 +* @author Grzegorz Kaczmarek +* @comment Code inspired on erlier Dwayne S. Dilbeck's work +* @date 20/11/2015 */ + #ifndef Max7221_H #define Max7221_H - -// define max7219/max7221 registers +// MAX7219/7221 register map #define max7219_reg_noop 0x00 -#define max7219_reg_digit0 0x01 -#define max7219_reg_digit1 0x02 -#define max7219_reg_digit2 0x03 -#define max7219_reg_digit3 0x04 -#define max7219_reg_digit4 0x05 -#define max7219_reg_digit5 0x06 -#define max7219_reg_digit6 0x07 -#define max7219_reg_digit7 0x08 #define max7219_reg_decodeMode 0x09 #define max7219_reg_intensity 0x0a #define max7219_reg_scanLimit 0x0b #define max7219_reg_shutdown 0x0c #define max7219_reg_displayTest 0x0f -#define LOW 0 -#define HIGH 1 -#define MHZ 1000000 -#define NUMDIGITS 8 - -#ifdef NUMDIGITS -#define UPPERBOUND 99999999 -#define LOWERBOUND -9999999 -#endif +// Logical values +#define LOG_0 0 +#define LOG_1 1 -/** - * Max7221 Example - * @code - * #include "mbed.h" - * #include "Max7221.h" - * - * - * // p5: DIN, p7: CLK, p8: LOAD/CS - * Max7221 max7221disp1(p5, p7, p8); - * //Max7221 max7221disp2(p5, p7, p8); - * //Max7221 max7221disp3(p11, p13, p14); - * //Max7221 max7221disp4(p11, p13, p14); - * - * int count=-99; - * - * void loop(void) { - * max7221disp1.WriteInt(count); - * if (count < 100) - * count=count+1; - * else - * count=-99; - * } - * - * int main() { - * max7221disp1.Setup(); - * //Max7221::SetupALl(); - * max7221disp1.WriteFloat(123.125); - * wait(1.0); - * - * while (1) { - * loop(); - * wait(1.0); - * } - * } - * @endcode - */ class Max7221 { +private: + SPI *mp_spi; // SPI used for this display (no data transmission when NULL) + DigitalOut *mp_cs; // CS signal (it should be handled manually when NULL) + unsigned int m_position; // Display position on SPI chain (0 = 1'st) + public: /** - * Constructor. This is the default constructor - * @author Dwayne S. Dilbeck - * @param msoi The SPI pin used as input to the device. Valid values for LPC1768 are p5 or p11 - * @param mclk The SPI pin used as clock for the device. Valid values for LPC1768 are p7 or p13 - * @param load The pin used to control load for the device. Any pin capable for DigitalOut can be used, but the same load pin must be used for - * device that share the same msoi and mclk pins - * @date 8/6/2013 + * Default constructor. + * @param spi Initialized SPI port used for communication with MAX7219/7221. + * @param cs Initialized output pin used as SW CS signal or NULL when HW one is used. + * @param position Position on SPI port (for displays connected in daisy-chain: DOUT-DIN). 0=1st. + */ + Max7221(SPI *spi, DigitalOut *cs, unsigned int position=0); + + /** + * Method for setting /CS signal LOW (enable data reception). */ - Max7221(PinName msoi=PTC6, PinName mclk=PTC5, PinName load=PTC4); + void CsLow(void); + + /** + * Method for setting /CS signal HIGH (received data is latched and processed). + */ + void CsHigh(void); + + /** + * Method used to send data over SPI (no use of /CS signal). + * To be used with display chains and when building display libraries + * where amount of data needs to be pushed via SPI in one transaction. + */ + void WriteRaw(unsigned int reg, unsigned int data); /** - * This method is used to write a byte of data to a specified register for only the device defined in this class instance - * @author Dwayne S. Dilbeck - * @param reg The register to write to. - * @param data The value to be written. - * @date 8/6/2013 + * Method for sending register-value pair for this diasplay. + * Supports display chain on single SPI (m_position > 0). */ - void Write( unsigned int reg, unsigned int data); + void Write(unsigned int reg, unsigned int data); /** - * This method is used to display an integer to the specified device instance. Underflow and overflow result in '-' written to all digits - * @author Dwayne S. Dilbeck - * @param value An integer value to display - * @date 8/6/2013 - */ - void WriteInt( int value ); + * Sets test mode which causes all display LEDs to emit light with full brightess. + * @param mode true - test mode, false - normal operation. + */ + void TestMode(bool mode); + + /** + * Sets amount of digits to be used by this display. + * @param digits_no 1 - one digit, (2-7), 8 - all 8 digits. + */ + void UseDigitsNo(unsigned int digits_no); /** - * This method is used to display a floating point number to the specified device instance. - * Underflow and overflow result in '-' written to all digits. The digits after the decimal - * point are truncated to fit the display. - * @author Dwayne S. Dilbeck - * @param value A float value to display - * @date 8/6/2013 - */ - void WriteFloat( float value); - - /** - * Overload of the EQUALS operator to provide easy use of the class. - * @author Dwayne S. Dilbeck - * @param value An integer value to display - * @date 8/6/2013 - */ - Max7221& operator= (int value){ - WriteInt(value); - return *this; - }; - /** - * Overload of the EQUALS operator to provide easy use of the class. - * @author Dwayne S. Dilbeck - * @param value A float value to display - * @date 8/6/2013 - */ - Max7221& operator= (float value){ - WriteFloat(value); - return *this; - }; + * Selects for which digits Code-B data decoding is used. + * @param mode 0x00 - no decoding, 0x0F - digits 0-3, 0xFF - all digits. + */ + void DecodeMode(unsigned int mode); /** - * This method is used to write an intial set off values to the device to prepare it for use. - * @author Dwayne S. Dilbeck - * @date 8/6/2013 - */ - void Setup (void); - - /** - * This method is used to write a byte of data to a specified register for all the devices instantiated. - * @author Dwayne S. Dilbeck - * @param reg The register to write to. - * @param data The value to be written. - * @date 8/6/2013 - */ - static void WriteAll (unsigned int reg, unsigned int data); + * Sends data to selected digit. + * @param digit_no Selected digit (0-7). + * @param digit_no Data to display. + */ + void WriteDigit(unsigned int digit_no, unsigned int value); /** - * This method is used to write an intial set off values to ALL device to prepare them for use. - * @author Dwayne S. Dilbeck - * @date 8/6/2013 + * Sets display brightness. + * @param intensity 0x00 - minimum brightness, 0x0F - maximum brightness. + */ + void Intensity(unsigned int intensity); + + /** + * Sets display operation mode. + * @param mode true - normal operation, false - shutdown mode. + */ + void OperationMode(bool mode); + + /** + * Initial setup of this display. + * 8-digit blank decimal display set to nimimal brightness. + * Supports display chain on single SPI (m_position > 0). */ - static void SetupAll (void); - -private: - /// Pointer for the class instance to a particular SPI bus - SPI *max7221_spi; - /// pointer for the class instance of a particular load signal - DigitalOut *max7221_cs; - /// id of the class instance - int id; - /// pointer to the number of devices connected to the SPI bus instance this device instance is connected to. - int *maxInUse; - - ///For the class we have a static set of values. There are 2 SPI buses, 2 load signals, and 2 counters of the number of devices connected to a SPI bus. - static SPI *spi; -// static SPI *spi2; - static DigitalOut *cs; -// static DigitalOut *load2; - static int maxInUseSPI; -// static int maxInUseSPI2; + void Setup(void); }; #endif \ No newline at end of file