Fix to have load pin working with SPI1.

Dependencies:   mbed

Fork of Max7221 by Dwayne Dilbeck

Max7221.cpp

Committer:
ky3orr
Date:
2015-11-19
Revision:
6:191569a26f50
Parent:
5:1f3dbf38d027
Child:
7:a160cb7cdd86

File content as of revision 6:191569a26f50:

/**
* @file Max7221.cpp
* @brief This file defines the Max7221 class methods and the default values for static variables
* 
* @author Dwayne S. Dilbeck
*
* @date 8/6/2013
*/
#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;
}

/**
*  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
    }
    ///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);
    }
    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;
    }
}
/**
*  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]);
  }
}

/**
*  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);

  // 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]);
      }
  }
}

/**
*  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);
    }
    WriteAll(max7219_reg_intensity, 0x01 & 0x0f);    // the first 0x0f is the value you can set
                                                  // range: 0x00 to 0x0f
}