HDSP253X Smart Alphanumeric LED matrix display

Dependents:   mbed_bus

Revision:
0:b3430a613781
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HDSP253X.cpp	Sun Jan 25 17:23:44 2015 +0000
@@ -0,0 +1,627 @@
+/* HDSP253X_Display - Intelligent 8 digit 5x7 LED matrix display
+ *
+ * Copyright (c) 2011 Wim Huiskamp
+ * Modified software based on sourcecode by RAC 06/08/2008
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+//#include "Utils.h"
+#include "PCF8574_DataBus.h"
+#include "PCF8574_AddressBus.h"
+#include "PCF8574_EnableBus.h"
+#include "MBED_ControlBus.h"
+#include "HDSP253X.h"
+
+/** Create an HDSP253X_Display object connected to the proper busses
+ *
+ * @param  PCF8574_DataBus data databus to connect to 
+ * @param  PCF8574_AddressBus address addressbus to connect to 
+ * @param  PCF8574_EnableBus enable enablebus to connect to 
+ * @param  MBED_ControlBus control controlbus to connect to 
+*/
+HDSP253X_Display::HDSP253X_Display (PCF8574_DataBus &databus, PCF8574_AddressBus &addressbus, PCF8574_EnableBus &enablebus, MBED_ControlBus &controlbus) : 
+                                     _databus(databus), _addressbus(addressbus), _enablebus(enablebus), _controlbus(controlbus) {
+
+   _init();
+}    
+
+/** Init HDSP253X_Display
+ * @param
+ * @returns 
+ */
+void HDSP253X_Display::_init(void)
+{
+    // Apply reset
+    reset();  // Note that this also resets the LED status display. 
+ 
+    // Note: Brightness is 100% after reset
+    set_brightness(HDSP253X_DEF_DISPLAY_BRIGHT);
+ 
+    // Reset cursor 
+    locate(0);
+}
+
+
+/*****************************************************************************/
+/*******************  LOW LEVEL HDSP253X SUPPORT FUNCTIONS  ******************/
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_reset
+ |
+ |  Description:    Reset routine for HDSP253X display, applying reset, 
+ |                  removing reset, then waiting for preset delay.
+ |                  With the internal clock, the delay should be around 1
+ |                  millisecond, but slower clocks will require longer delays.
+ |                  After reset the Char RAM and Flash RAM is cleared, the CTRL word is
+ |                  cleared (Blink Off, Flash Off, Brightness 100%). UDC RAM and address
+ |                  are unaffected.
+ |
+ |  Parameters:     None
+ |
+ |  Returns:        Nothing.
+ |
+\*---------------------------------------------------------------------------*/
+void HDSP253X_Display::reset(void)
+{
+//NOTE: On LF28A the Reset* pin is connected to the display and to the latches.
+//      That implies they are all reset when the Reset* pin is used !
+// 
+// Alternative for the Display may be SW reset instruction
+
+    // Apply the reset condition and then remove after short delay
+    _enablebus.chipselect(CS_DISP, HIGH);  
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+    
+    _enablebus.reset(LOW);   
+    wait_ms(HDSP253X_1TCY_WAIT_MS);    
+    wait_ms(HDSP253X_1TCY_WAIT_MS);        
+    _enablebus.reset(HIGH);             
+    
+    // Wait for the preset delay to allow operation to complete
+    wait_ms(HDSP253X_RST_CLR_DELAY_MS);
+    
+    // Reset cursor 
+    locate(0);
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_write
+ |
+ |  Description:    Low level data write routine for HDSP253X. Takes in data
+ |                  and address (including Flash as top bit) and writes
+ |                  it to the display. For simplicity, entire address byte
+ |                  is written, even though top two bits are unused inputs.
+ |                  After performing the operation, address lines are set
+ |                  all high, in order to eliminate current drain through
+ |                  pullup resistors (0.5mA per pin with 10K pullups)
+ |
+ |  Parameters:     address - full address in bits 0-5 (bit 5 is flash)
+ |                  data - data byte to write out
+ |
+ |  Returns:        Nothing.
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::_write(uint8_t address, uint8_t data)
+{
+//    // Switch databus buffer to outputs
+//    _controlbus.busdir(WRITE);        
+//    // Switch databus to outputs
+//    _databus.busdir(WRITE);   
+
+    
+    // Write out the address on to the addressbus and wait
+    _addressbus.write(address);
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set CE low and wait
+    _enablebus.chipselect(CS_DISP, LOW);  
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Write data to the databus
+    _databus.write(data);        
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+     
+    // Set WR low, wait, then set high and wait
+    _controlbus.WR(LOW);
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+    _controlbus.WR(HIGH);
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set CE high and wait
+    _enablebus.chipselect(CS_DISP, HIGH);  
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+    
+//    // Switch databus back to inputs
+//    _databus.busdir(READ);        
+//    // Switch databus buffer back to inputs
+//    _controlbus.busdir(READ);  
+
+//    // Set address lines all high to minimise power through pullups
+//    _addressbus.write(HDSP253X_ADDR_LOW_POWER);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_read
+ |
+ |  Description:    Low level data read routine for HDSP253X. Takes in 
+ |                  address (including Flash as top bit) and reads data
+ |                  from the display. For simplicity, entire address byte
+ |                  is written, even though top two bits are unused inputs.
+ |                  After performing the operation, address lines are set
+ |                  all high, in order to eliminate current drain through
+ |                  pullup resistors (0.5mA per pin with 10K pullups)
+ |
+ |  Parameters:     address - full address in bits 0-5 (bit 5 is flash)
+ |
+ |  Returns:        data - data byte read in (Note that D7 is masked out)
+ |
+\*---------------------------------------------------------------------------*/
+
+uint8_t HDSP253X_Display::_read(uint8_t address)
+{
+    uint8_t data = 0;
+
+    // Switch databus to inputs
+    _databus.busdir(READ);        
+    // Switch databus buffer to inputs
+    _controlbus.busdir(READ);      
+       
+    // Write out the address on to the addressbus and wait
+    _addressbus.write(address);
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set CE low and wait
+    _enablebus.chipselect(CS_DISP, LOW);
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set RD low and wait
+    _controlbus.RD(LOW);
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+    
+    // Read the data byte from databus
+    // Mask out the not-readable D7 bit, this mask is needed for my specific targetboard !
+    // Reading the unconnected D7 bit results in 'H' level. A RMW cycle on the Ctrl register
+    // would then always result in a Clearscreen !
+    data = _databus.read() & HDSP253X_CTRL_MASK;
+
+    // set RD high and wait
+    _controlbus.RD(HIGH);
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set CE high and wait
+    _enablebus.chipselect(CS_DISP, HIGH);
+//    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+//    // Set address lines all high to minimise power through pullups
+//    _addressbus.write(HDSP253X_ADDR_LOW_POWER);
+
+    // Switch databus buffer back to outputs
+    _controlbus.busdir(WRITE);        
+    // Switch databus to outputs
+    _databus.busdir(WRITE);   
+    
+    // Return read data to caller
+    return data;
+}
+
+
+/*****************************************************************************/
+/**************  HIGH LEVEL HDSP253X CHARACTER DISPLAY FUNCTIONS  ************/
+/*****************************************************************************/
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_putudc
+ |
+ |  Description:    Displays specified UDC character on the display at current
+ |                  position. Used defined characters use codes from 128-142.
+ |                  Note that the normal putc write routines can also be used
+ |                  to show UDCs, using ASCII values 128 to 143 inclusive.
+ |
+ |  Parameters:     udc_char_num - UDC character, 16 possible UDC values from 0-15
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::putudc (char udc_char_num)
+{
+  putc(HDSP253X_ASCII_UDC_CHARS + udc_char_num);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_printf
+ |
+ |  Description:    Displays specified string on the display at current
+ |                  cursor position. Increments cursor.
+ |
+ |  Parameters:     format - format string
+ |                  args   - data
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::printf (char * format, ...) {
+   char display_string[64];
+//   int rv;   
+   int string_len, i;   
+   va_list args;
+   va_start (args, format);
+
+//   rv=vsprintf (display_string, format, args);
+   vsprintf (display_string, format, args);   
+   va_end (args);   
+// printf("printing:'%s'\n", display_string);
+//   writeString (buffer);
+
+   // loop round, writing characters
+   string_len = strlen(display_string);   // obtain length of string
+   for (i = 0; i < string_len; i++) {
+     putc(display_string[i]);
+   };
+
+   // return rv;
+}
+
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_putc
+ |
+ |  Description:    Displays specified character on the display at current
+ |                  cursor position. Increments cursor.
+ |                  Position on the display (0 to 7, Leftmost = 0)
+ |
+ |  Parameters:     disp_char - single character to display
+ |                    - ASCII characters, 128 values between 0-127
+ |                    - UDC character, 15 possible UDC values from 128-142
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+void HDSP253X_Display::putc(char disp_char) {
+
+    // Write selected character to display at current position
+   
+    if ((disp_char & HDSP253X_UDC_SEL) == HDSP253X_UDC_SEL) {      
+        // Write UDC character to display, code between 128-143
+        disp_char &= HDSP253X_UDC_MASK;        // mask off unused bits
+        disp_char |= HDSP253X_UDC_SEL;         // add in top bit to specify UDC        
+        _write(HDSP253X_ADDR_CHAR_BASE + _column, disp_char);
+    }
+    else {
+        // Write ASCII character, code between 0-127
+        disp_char &= HDSP253X_CHAR_MASK;        // mask off unused bits
+        _write(HDSP253X_ADDR_CHAR_BASE + _column, disp_char);        
+    }
+    
+    // Incr and wrap around cursorposition
+    _column++; 
+    _column = _column % HDSP253X_NUM_CHARS;    
+}
+
+
+
+#if(0)
+char HDSP253X_Display::getc() {
+  return -1;
+}
+#endif
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_locate
+ |
+ |  Description:    Set the cursor address where the next character will be written. 
+ |
+ |  Parameters:     Cursor Column address
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::locate(uint8_t column) {
+
+//    _row = row % HDSP253X_NUM_ROWS;
+    _column = column % HDSP253X_NUM_CHARS;
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_cls
+ |
+ |  Description:    Clears the displayed data and flash RAM, but not the user
+ |                  defined characters. Waits for the preset delay to ensure the 
+ |                  display is ready for operation; with an internal clock,
+ |                  this delay needs to be around 1 millisecond. 
+ |
+ |  Parameters:     None
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::cls(void) {
+
+    uint8_t disp_data;
+
+    // Read in control word, modify and write back out
+    disp_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    disp_data |= HDSP253X_CTRL_CLEAR_MASK;
+    _write(HDSP253X_ADDR_CTRL_WORD, disp_data);
+
+    // Wait for the preset delay to allow operation to complete
+    wait_ms(HDSP253X_RST_CLR_DELAY_MS);
+
+    // Reset cursor 
+    locate(0);
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_brightness
+ |
+ |  Description:    Sets the brightness of the HDSP253X display, by performing
+ |                  a read-modify-write on the control register.
+ |
+ |  Parameters:     brightness - 3 bit brightness value
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_brightness(uint8_t brightness) {
+
+    uint8_t ctrl_data;
+
+    // Read in control word, modify and write back out
+    ctrl_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    ctrl_data &= ~HDSP253X_CTRL_BRIGHT_MASK;
+    ctrl_data |= (brightness & HDSP253X_CTRL_BRIGHT_MASK);
+    _write(HDSP253X_ADDR_CTRL_WORD, ctrl_data);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_start_self_test
+ |
+ |  Description:    Starts the HDSP253X self test, setting the relevant 
+ |                  control word bit. The caller should then wait for 
+ |                  the required number of seconds before checking the result.
+ |                  With the internal display clock, the self test takes 
+ |                  around 5 seconds, so waiting for 6 seconds should
+ |                  be OK. Slower clocks will require longer delays.
+ |
+ |                  Note that some displays such as the Siemens HDSP2111
+ |                  appear to take longer than the official 4.5 seconds
+ |                  so it is advisable to wait for longer (say 6 seconds)
+ |                  before checking the result. Attempting to access the
+ |                  display before it is ready may result in the self test
+ |                  status failing to clear down.
+ |
+ |                  Also note that some display datasheets suggest that
+ |                  the display must be reset BEFORE running the self
+ |                  test routine, so this routine does this.
+ |
+ |  Parameters:     None
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::start_self_test(void) {
+
+    // Reset the display to ensure it is ready for the self test
+    reset();
+
+    // Directly write the self test request, as control word is wiped at end
+    _write(HDSP253X_ADDR_CTRL_WORD, HDSP253X_CTRL_SELFTEST_MASK);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_finish_self_test
+ |
+ |  Description:    Reads the control register to determine the self test
+ |                  result. Then issues a display reset to ensure 
+ |                  that it is ready for operation afterwards. While such
+ |                  a reset should not be necessary if an adequate delay
+ |                  occurs between starting the self test and checking the 
+ |                  result, issuing a reset guarantees that the display will 
+ |                  be ready for operation. This also means that this function
+ |                  can be called early to prematurely terminate a self test.
+ |
+ |  Parameters:     None
+ |
+ |  Returns:        True if passed, False if failed
+ |
+\*---------------------------------------------------------------------------*/
+
+bool HDSP253X_Display::finish_self_test(void) {
+    uint8_t ctrl_data;
+    bool result;
+    
+    // Read back control word and obtain self test result
+    ctrl_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    result = ((ctrl_data & HDSP253X_CTRL_STRESULT_MASK) != 0);
+
+    // Reset the display to ensure it is ready for normal operation
+    reset();
+
+    // Indicate the self test result
+    return result;
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_blink_mode
+ |
+ |  Description:    Enables or disables the blinking function on the display.
+ |                  When enabled, blinking will flash the whole display 
+ |                  irrespective of the flash RAM. With the internal clock,
+ |                  the blink rate is 2Hz. Note that blink mode overrides 
+ |                  the normal flashing mode.
+ |
+ |  Parameters:     enable - true to enable, false to disable
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_blink_mode(bool enable) {
+    uint8_t ctrl_data;
+
+    // read in control word, modify and write back out
+    ctrl_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    if (enable) {
+      ctrl_data |= HDSP253X_CTRL_BLINK_MASK;
+    }
+    else {
+      ctrl_data &= ~HDSP253X_CTRL_BLINK_MASK;
+    }
+    _write(HDSP253X_ADDR_CTRL_WORD, ctrl_data);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_flash_mode
+ |
+ |  Description:    Enables or disables the flashing function on the display.
+ |                  When enabled, characters with the flashing bit set in the 
+ |                  RAM will flash. With the internal clock, the flash rate is 2Hz.
+ |
+ |  Parameters:     enable - true to enable, false to disable
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_flash_mode(bool enable) {
+    uint8_t ctrl_data;
+
+    // read in control word, modify and write back out
+    ctrl_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    if (enable) {
+      ctrl_data |= HDSP253X_CTRL_FLASH_MASK;
+    }
+    else {
+      ctrl_data &= ~HDSP253X_CTRL_FLASH_MASK;
+    }
+    _write(HDSP253X_ADDR_CTRL_WORD, ctrl_data);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_all_flash_states
+ |
+ |  Description:    Sets flashing states of all characters in flash RAM, using 
+ |                  supplied bit mask. Each bit corresponds to a character
+ |                  (bit 7 on left, bit 0 on right), and is set to flash and
+ |                  clear for steady operation. NOTE: The overall flashing 
+ |                  enable/disable state is set by the separate set flash 
+ |                  mode function.
+ |
+ |  Parameters:     flash_bits - bitmask containing flash states
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_all_flash_states(uint8_t flash_bits)
+{
+    int i;
+    uint8_t char_pos;
+
+    // loop round all character positions, extracting each bit in turn
+    for (i = 1; i <= HDSP253X_NUM_CHARS; i++)
+    {
+      // Get state of bottom bit from mask and use to adjust flash state
+      // Note that character address is reversed as we start from right
+      char_pos = HDSP253X_NUM_CHARS - i;
+      _write(HDSP253X_ADDR_FLASH_BASE + char_pos, flash_bits & 0x01);
+
+      // Shift the mask to the right, ready for the next go
+      flash_bits >>= 1;
+    }
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_char_flash_state
+ |
+ |  Description:    Sets flashing state of one character in flash RAM, using 
+ |                  supplied character position and enable state. NOTE: The 
+ |                  overall flashing enable/disable state is set by the 
+ |                  separate set flash mode function.
+ |
+ |  Parameters:     flash_state - TRUE to flash, FALSE for steady operation
+ |                  char_pos - position on the display (0 to 7)
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_char_flash_state(bool flash_state, uint8_t char_pos) {
+    // Write out the new flash state to the flash RAM
+    _write(HDSP253X_ADDR_FLASH_BASE + char_pos, flash_state);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_define_user_char
+ |
+ |  Description:    Full definition of UDC, firstly setting the UDC address
+ |                  to specified character, and then loading all 7 data rows.
+ |                  Note that for each row, only the bottom 5 bits are used.
+ |  
+ |  Parameters:     udc_char_num - number of UDC character, from 0 to 15
+ |                  row_data_1 - top row data
+ |                  row_data_2 - second row data
+ |                  row_data_3 - third row data
+ |                  row_data_4 - fourth row data
+ |                  row_data_5 - fifth row data
+ |                  row_data_6 - sixth row data
+ |                  row_data_7 - bottomp row data
+ |  
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::define_user_char(uint8_t udc_char_num, uint8_t row_data_1, uint8_t row_data_2,
+                                        uint8_t row_data_3, uint8_t row_data_4, uint8_t row_data_5, 
+                                        uint8_t row_data_6, uint8_t row_data_7)
+{
+    // firstly set the UDC character address, by writing to the UDC addr reg
+    _write(HDSP253X_ADDR_UDC_ADDRESS, udc_char_num);
+
+    // now write out the 7 rows to the UDC RAM
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+0, row_data_1);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+1, row_data_2);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+2, row_data_3);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+3, row_data_4);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+4, row_data_5);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+5, row_data_6);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+6, row_data_7);
+}
+
+
+/*****************************************************************************/
+/******************************  END OF FILE  ********************************/
+/*****************************************************************************/
+