Alphanumeric LED display, 8 digits, 5x7 pattern. Supports 8x1, 8x2, 16x1 and 16x2 display configuration.

Dependents:   mbed_HCMS2975

Alphanumeric LED display, 8 digits, 5x7 LED pattern. The device has SPI interface. The library supports multiple devices connected in a daisy chain. This provides a 8x1, 8x2, 16x1 and 16x2 display configuration.The library methods are similar to those used for the LCDText library.

/media/uploads/wim/hcms2975.jpg

These displays are from mid 80s to mid 90s and they look cool, but they are rather expensive ($100 a piece..). The lib was developed and tested with displays salvaged from some equipment. You see them mostly in HP printers, medical equipment etc.

Some info can be found here and here.

Datasheet is here

HCMS2975.cpp

Committer:
wim
Date:
2015-01-05
Revision:
1:f46d90374eb2
Parent:
0:a332431006fb

File content as of revision 1:f46d90374eb2:

/** 
 * @file HCMS2975.cpp 
 * @brief  mbed Avago/HP HCMS2975 LED matrix display Library. 
 * @author WH
 * @date   Copyright (c) 2014
 *         v01: WH, Initial release
 *              Info available at http://playground.arduino.cc/Main/LedDisplay and http://www.pjrc.com/teensy/td_libs_LedDisplay.html 
 *         v02: WH, added getVersion()  
 *         v03: WH, fixed setBrightness at init() when there is no HW reset.   
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "mbed.h"
#include "HCMS2975.h"
#include "font_5x7.h" // Pascal Stang's 5x7 font library

// User Defined Characters (UDCs) are defined by a 5 byte bitpattern. The P0..P6 form the character pattern, P7 is ignored.
//     Byte0 Byte1 Byte2 Byte3 Byte4 
// b0  P0    P0    P0    P0    P0
// b1  P1    P1    P1    P1    P1
// .         .............
// b6  P6    P6    P6    P6    P6
// b7  x     x     x     x     x 

/** Some sample User Defined Chars 5x7 dots */
const char udc_0[]      = {0x7F, 0x41, 0x22, 0x14, 0x08};  /* |> */
const char udc_1[]      = {0x08, 0x14, 0x22, 0x41, 0x7F};  /* <| */
const char udc_2[]      = {0x7F, 0x00, 0x00, 0x00, 0x00};  /* |  */
const char udc_3[]      = {0x7F, 0x00, 0x7F, 0x00, 0x00};  /* || */
const char udc_4[]      = {0x7F, 0x00, 0x7F, 0x00, 0x7F};  /* ||| */
const char udc_5[]      = {0x2A, 0x2A, 0x2A, 0x2A, 0x2A};  /* = */
const char udc_6[]      = {0x55, 0x2A, 0x55, 0x2A, 0x55};  /* checkerboard */
const char udc_7[]      = {0x01, 0x02, 0x04, 0x08, 0x10};  /* \ */

const char udc_Bat_Hi[] = {0x7E, 0x7F, 0x7F, 0x7F, 0x7E};  /* Battery Full */
const char udc_Bat_Ha[] = {0x7E, 0x7D, 0x7D, 0x7D, 0x7E};  /* Battery Half */
const char udc_Bat_Lo[] = {0x7E, 0x61, 0x61, 0x61, 0x7E};  /* Battery Low */
const char udc_AC[]     = {0x0C, 0x17, 0x74, 0x17, 0x0C};  /* AC Power */
const char udc_smiley[] = {0x10, 0x22, 0x28, 0x22, 0x10};  /* Smiley */

/** Create an HCMS2975 Display object connected to the proper pins
  *
  * @param  *spi SPI port
  * @param  cs   PinName for Chip Select (active low)
  * @param  rs   PinName for RS ()
  * @param  rst  PinName for Rst (active low, optional, default=NC) 
  * @param type  Sets the panel size (default = LED8x1)     
  */
HCMS2975::HCMS2975(SPI *spi, PinName cs, PinName rs, PinName rst, LEDType type) : _spi(spi), _cs(cs), _rs(rs), _type(type) {
  
  // Extract LCDType data  

  // Columns encoded in b7..b0
  _nr_cols = (_type & 0xFF);          

  // Rows encoded in b15..b8  
  _nr_rows = ((_type >> 8) & 0xFF);  
  
  _displaySize = _nr_cols * _nr_rows;

  // Number of devices encoded in b23..b16  
  _deviceCount = ((_type >> 16) & 0xFF);  


  // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
  if (rst != NC) {
    _rst = new DigitalOut(rst);   //Construct new pin 
    _rst->write(1);               //Deactivate    
  }
  else {
    // No Hardware Backlight pin       
    _rst = NULL;                 //Construct dummy pin     
  }  

  _init();    
}

/** Destructor for HCMS2975 Display object
  *
  */ 
HCMS2975::~HCMS2975() {
   if (_rst != NULL) {delete _rst;}  // RST pin
}

#if(HCMS2975_PRINTF != 1)
/** Write a character to the Display
  *
  * @param c The character to write to the display
  */
int HCMS2975::putc(int c){
  return _putc(c);  
}

/** Write a raw string to the Display
  *
  * @param string text, may be followed by variables to emulate formatting the string.
  *                     However, printf formatting is NOT supported and variables will be ignored! 
  */
int HCMS2975::printf(const char* text, ...) {
  
  while (*text !=0) {
    _putc(*text);
    text++;
  }
  return 0;
}
#else    
#if DOXYGEN_ONLY
/** Write a character to the Display
  *
  * @param c The character to write to the display
  */
int HCMS2975::putc(int c){
    return _putc(c);
}

/** Write a formatted string to the Display
  *
  * @param format A printf-style format string, followed by the
  *               variables to use in formatting the string.
  */
int HCMS2975::printf(const char* format, ...){
}   
#endif
    
#endif    

/** Clear the screen and locate to 0,0
  */
void HCMS2975::cls(){

  // fill _displayBuffer with spaces
  for (int i=0; i < HCMS2975_BUFFER_SIZE; i++) {
    _displayBuffer[i] = ' ';
  }
    
  // display buffer  
  _pushBuffer();
  
  //cursor
  _row = 0;
  _column = 0;     
}                              

/** Locate cursor to a screen column and row
  *
  * @param column  The horizontal position from the left, indexed from 0
  * @param row     The vertical position from the top, indexed from 0
  */
void HCMS2975::locate(int column, int row){

// Sanity Check column
    if (column < 0) {
      _column = 0;
    }
    else {
      if (column >= _nr_cols) {
        _column = _nr_cols - 1;
      }
      else {
        _column = column;
      }
    }
    
// Sanity Check row
    if (row < 0) {
      _row = 0;
    }
    else {
      if (row >= _nr_rows) {
        _row = _nr_rows - 1;
      }
      else { 
        _row = row;
      }  
    }  
}

/** Return the number of columns
  *
  * @return int The number of columns
  */   
int HCMS2975::columns() {
    
  // Columns encoded in b7..b0
  //return (_type & 0xFF);          
  return _nr_cols;           
}

/** Return the number of rows
  *
  * @return int The number of rows
  */
int HCMS2975::rows() {

  // Rows encoded in b15..b8  
  //return ((_type >> 8) & 0xFF); 
  return _nr_rows;          
}


/** Set Brightness
  *
  * @param brightness The brightness level (valid range 0..15)
  */
void HCMS2975::setBrightness(uint8_t brightness){

  _brightness = brightness & 0x0F;    

  //Set brightness
  //Set display to normal
  _writeCommand(HCMS2975_CONTROL0 | HCMS2975_NORMAL | _peak | _brightness);
}  

/** Set the Displaymode
  *
  * @param displayMode The Display mode (DispOff, DispOn)
  */
void HCMS2975::setMode(DisplayMode displayMode){
    
  if (displayMode == DispOff) {
    //Set brightness to Zero
    _writeCommand(HCMS2975_CONTROL0 | HCMS2975_NORMAL | _peak | HCMS2975_BRIGHT_0);   
//    //Set Sleep mode    
//    _writeCommand(HCMS2975_CONTROL0 | HCMS2975_SLP | _peak | _brightness);       
  }  
  else {
    //Restore brightness
    //Set display to normal
    _writeCommand(HCMS2975_CONTROL0 | HCMS2975_NORMAL | _peak | _brightness);   
  }
}     

/** Set User Defined Characters (UDC)
  *
  * @param unsigned char c   The Index of the UDC (0..7)
  * @param char *udc_data    The bitpatterns for the UDC (5 bytes of 7 significant bits for bitpattern)       
  */
void HCMS2975::setUDC(unsigned char c, char *udc_data){
  char *udc;
  int idx;
  
  c = c & 0x07; // mask to valid range
  
  udc = (char *) _udc[c];

  // Copy UDC data to local UDC memory
  for (idx=0; idx < 5; idx++) {
    *udc++ = *udc_data++; 
  }
}   
  

/** Low level Reset method for controller
  */  
void HCMS2975::_reset(){

  // Reset when pin defined
  if (_rst) {
    _rst->write(0);   
    wait_us(500);    
    _rst->write(1);       
  }      
}
    
/** Low level Init method for controller
  */  
void HCMS2975::_init(){ 

  // Hard Reset
  _reset();
      
  // Init CS en RS
  _cs = 1;
  _rs = 0;

  // Setup the spi for 8 bit data, low steady state clock,
  // rising edge capture, with a 500KHz or 1MHz clock rate  
  _spi->format(8,0);
  _spi->frequency(1000000);    // Max SCL is 5 MHz for HCMS2975
//  _spi->frequency(50000);    // Max SCL is 5 MHz for HCMS2975

  //Set display to serial mode
  _writeCommand(HCMS2975_CONTROL1 | HCMS2975_PRE_1 | HCMS2975_SERIAL);

  // default display brightness and peak
  _brightness = HCMS2975_DEF_BRIGHT;
  _peak       = HCMS2975_DEF_PEAK;
   
  //Set display to normal
  _writeCommand(HCMS2975_CONTROL0 | HCMS2975_NORMAL | _peak | _brightness);

  //Clear display
  cls();
} 
 
 
/** Low level command byte write operation.
  * @param command commandbyte to write
  */
void HCMS2975::_writeCommand(uint8_t command){
  int cnt;
  
  // Set RS 
  _rs = 1;
  wait_us(1);
    
  // Enable CS
  _cs = 0;
  wait_us(1);
  
  // Must write the command to all devices...!
  // Note that internally the 8 digit display consist of 2 display devices with 4 digits each!
  for (cnt=0; cnt < (_deviceCount << 1); cnt++) {
    _spi->write(command);         
    // wait_us(1);  // Min setup time is x ns for HCMS2975    
  }  
   
  // Disable CS
  _cs = 1;

  // Reset RS 
  _rs = 0; 
  
}

/** Low level _dataBuffer write operation.
  */
void HCMS2975::_pushBuffer(){
  char charcode;
  char *fnt_ptr;
  int idx, pidx;
   
  // Reset RS 
  _rs = 0; 
  wait_us(1);  
  
  // Enable CS
  _cs = 0;
  wait_us(1);

  // Encode and push the character data to the display
  for (idx=0; idx < _displaySize; idx++) {
    charcode = _displayBuffer[idx];
    
    //Sanity check and font pointer
    if (charcode < 0x08) {
      //UDC  
      fnt_ptr = (char *) _udc[charcode];           
    }
    else {
      if ((charcode < 0x20) || (charcode > 0x7F)) {
        // non-printable, show 'space'
        fnt_ptr = (char *) font_5x7[0];                      
      }
      else {
        //Pointer to char pattern 
        fnt_ptr = (char *) font_5x7[charcode - 0x20];       
      }
    } // end sanity check 
        
    //Write char pattern of 5 bytes
    for (pidx=0; pidx < 5; pidx++) {
      _spi->write(*fnt_ptr);
      fnt_ptr++;
      //wait_us(1);  // Min setup time is x ns for HCMS2975      
    } //for pidx
 
  } //for idx
 
  // Disable CS
  _cs = 1;
    
}


// Stream implementation functions
int HCMS2975::_putc(int value){
 
  if ((value == '\n') || (value == '\r')) {
    //No character to write
       
    //Update Cursor      
    _column = 0;
    _row++;
    if (_row >= _nr_rows) {
      _row = 0;
    }
    
    return 0;
  }          
  else {
    //Character to write      
    _displayBuffer[(_row * _nr_cols) + _column] = value; 
              
    //Update Cursor
    _column++;
    if (_column >= _nr_cols) {
      _column = 0;
      _row++;
      if (_row >= _nr_rows) {
        _row = 0;
      }
    }
    
    // push new data to display
    _pushBuffer();
    
    return 0;              
  } //else
 
}


// Stream implementation functions
int HCMS2975::_getc(){
  return -1;    
}


/** Returns the version number of the library
  * @return int version number
  */
int HCMS2975::getVersion() {
  return HCMS2975_VERSION;
}