Library for "I2C 8x8 LED matrix board" from Switch Science https://www.switch-science.com/catalog/2071/

Dependents:   PCA9622_LED8x8_Demo PCA9622_LED8x8_Hello PCA9622_LED8x8_x6_Demo shake-shake-machine

0. What is this?

I2C interface single color LED matrix module with PCA9622(LED controller).

This library provides interface from memory array to LEDs, manages scan.
Brightness control can be done for each pixels by setting data as float value (from 0.0 to 1.0).

topview
bottomview

1. How to use

1.1 Sample code

Import programPCA9622_LED8x8_Hello

This is a very simple sample code for the PCA9622_LED8x8 library. arget hardware : "I2C 8x8 LED matrix board" from Switch Science https://www.switch-science.com/catalog/2071/

1.2 Very basic sample

1.2.1 Displaying static image

Next is simplified code sample that makes still image on the LEDs.
In the main() function, the library operation is started by start() function and image data is set by set_data().
The image data is stored in 2 dimensional float array.

#include "mbed.h"
#include "PCA9622_LED8x8.h"

PCA9622_LED8x8  matrix( p28, p27 );     //  I2C pins. SDA and SCL

int main()
{
    float   image[ 8 ][ 8 ];

    matrix.start();

    //  making 8x8 image to "image" array
    for ( int i = 0; i < 8; i++ )
        for ( int j = 0; j < 8; j++ )
            image[ i ][ j ]   = (i + 1) * (j + 1) / 64.0;

    //  set the image into library internal bufer
    matrix.set_data( image );

    while(1)
        ;
}


/media/uploads/nxp_ip/img_3560.jpg
result of upper code

1.2.2 Image array elements' physical position

Each element of "float image[8][8]" array has physical position of..

leftright
topimage[0][0]image[0][1]image[0][2]image[0][3]image[0][4]image[0][5]image[0][6]image[0][7]
image[1][0]image[1][1]image[1][2]image[1][3]image[1][4]image[1][5]image[1][6]image[1][7]
image[2][0]image[2][1]image[2][2]image[2][3]image[2][4]image[2][5]image[2][6]image[2][7]
image[3][0]image[3][1]image[3][2]image[3][3]image[3][4]image[3][5]image[3][6]image[3][7]
image[4][0]image[4][1]image[4][2]image[4][3]image[4][4]image[4][5]image[4][6]image[4][7]
image[5][0]image[5][1]image[5][2]image[5][3]image[5][4]image[5][5]image[5][6]image[5][7]
image[6][0]image[6][1]image[6][2]image[6][3]image[6][4]image[6][5]image[6][6]image[6][7]
bottomimage[7][0]image[7][1]image[7][2]image[7][3]image[7][4]image[7][5]image[7][6]image[7][7]

1.2.3 Making the image moving

If you want to perform animation on the LEDs, it can be done by simple loop.
Keep the loop doing (1) store image data into the array and () call set_data() function.
The set_data() function can be called any time.

The set_data() function does copy the data in in-active side of internal buffer.
This library has two 8x8 buffers internally to perform "ping-pong" buffering. One side of the buffer is "active" and other side is "inactive".
The active side is the buffer for displaying data to LEDs. The inactive side is for user access.
The set_data() always access to the inactive side and after the inactive side filling is done, the active/inactive side switched at next scan start.

    while(1)
    {
        //  do something for image array to store data;
        ....
        ...
        matrix.set_data( image );
        wait( 0.1 );
    }

2. Tips

2.1 Frame rate

To minimize the flicker, default setting of frame rate is set to 100Hz.
But it is bit heavy rate to maintain the scan by MCU. If you going to use multiple modules, you may need to lower the I2C clock frequency.

Since mbed's I2C write routine is blocking function, frequent I2C transfer consumes much CPU time (just to wait transfer complete). To draw a line, one I2C transfer is done (14 bytes transfer including slave address). If the frame rate is 100Hz, 800 times I2C transfer happens in a second (8 lines/frame * 100Hz). If your mbed is supporting "I2C Fast mode plus (Fm+)", this will be a good option to reduce the CPU load. PCA9622 supports Fm+ which can handle the clock upto 1MHz.

2.2 Start/Stop

After start() function call, a periodic interrupt is installed to maintain the scanning the LEDs. This will be kept until stop() function called.

3. Links

shop page (Japanese)
schematic
PCA9622

Component page is available

Please refer to the component page for for more information.

I2C 8x8 LED matrix board" from Switch Science

Information

If you want to try displaying image which is prepared as file (PNG, JPEG, GIF, BMP, etc.), this tool may be useful.
This tool converts the image data into float array (in C source format).
https://gist.github.com/toyowata/bf576ee091e75071bc66

PCA9622_LED8x8.h

Committer:
nxp_ip
Date:
2015-02-26
Revision:
3:fb23972da0f3
Parent:
2:cd00372373e4

File content as of revision 3:fb23972da0f3:

/**
 *  PCA9622 LED 8x8 library
 *
 *  @author  Tedd OKANO
 *  @version 1.1.1
 *  @date    26-Feb-2015
 *
 *  Library for "I2C 8x8 LED matrix board" from Switch Science
 *    https://www.switch-science.com/catalog/2071/
 *
 *  The I2C LED controller PCA9622 is used on this module
 *  This LED controller chip enables brightness control by PWM.
 *
 *  For more information about the PCA9622:
 *    http://www.nxp.com/documents/data_sheet/PCA9622.pdf
 */

#ifndef MBED_PCA9622_LED8x8_H
#define MBED_PCA9622_LED8x8_H

#include "mbed.h"

/** PCA9622_LED8x8 class
 *
 *  PCA9622_LED8x8: A library to control LED matrix using the PCA9622
 *
 *  PCA9622 is an I2C LED controller.
 *  This library operates LED 8x8 matrix through the PCA9622.
 *
 *  Example:
 *  @code
 *  #include "mbed.h"
 *  #include "PCA9622_LED8x8.h"
 *
 *  PCA9622_LED8x8  matrix( p28, p27 );     //  for 40pin type mbed
 *  //PCA9622_LED8x8  matrix( D14, D15 );   //  for Arduino type mbed
 *  //PCA9622_LED8x8  matrix( dp5, dp27 );  //  for mbed LPC1114
 *
 *  float func( float x, float y, float t );    //  function to make 8x8 image
 *
 *  int main()
 *  {
 *      float   image[ 8 ][ 8 ];  //
 *      int     count   = 0;
 *
 *      matrix.start();
 *
 *      while(1) {
 *
 *          //  making 8x8 image to "image" array
 *          for ( int i = 0; i < 8; i++ )
 *              for ( int j = 0; j < 8; j++ )
 *                  image[ i ][ j ]   = func( i, j, count * 0.2 );
 *
 *          matrix.set_data( image );
 *
 *          count++;
 *          wait( 0.05 );
 *      }
 *  }
 *
 *  float func( float x, float y, float t )
 *  {
 *  //#define     DISPLAY_OFFSET  3.5
 *  #define     DISPLAY_OFFSET  0
 *  #define     SIZE            0.3
 *
 *      float   s;
 *
 *      x   = (x - DISPLAY_OFFSET) * SIZE;
 *      y   = (y - DISPLAY_OFFSET) * SIZE;
 *
 *      s   = cos( powf( x * x + y * y, 0.5 ) - t );
 *      return ( powf( s, 4.0 ) );
 *  }
 *  @endcode
 */

class PCA9622_LED8x8
{
public:
    enum FrameRate { DEFAULT_FRAMERATE   = 50 };

    /** Create a PCA9622_LED8x8 instance for the LED matrix board
     *  which is connected to specified I2C pins with specified address
     *
     * @param sda I2C-bus SDA pin
     * @param scl I2C-bus SCL pin
     * @param slave_adr (option) I2C-bus address (default: 0xA0)
     * @param fr (option) frame rate (in "Hz". default: 100)
     */
    PCA9622_LED8x8( PinName sda, PinName scl, char slave_adr = 0xA0, float fr = DEFAULT_FRAMERATE );

    /** Create a PCA9622_LED8x8 instance for the LED matrix board
     *  which is connected to specified I2C pins with specified address
     *
     * @param i2c_obj I2C object (instance)
     * @param slave_adr (option) I2C-bus address (default: 0xA0)
     * @param fr (option) frame rate (in "Hz". default: 100)
     */
    PCA9622_LED8x8( I2C &i2c_obj, char slave_adr = 0xA0, float fr = DEFAULT_FRAMERATE );

    /** Destructor of PCA9622_LED8x8
     */
    ~PCA9622_LED8x8();

    /** Frame rate change
     *
     *  Changes frame rate (scan rate of the matrix)
     *
     * @param rate Frame rate in "Hz"
     */
    void    frame_rate( float rate );

    /** Start operation
     *
     *  The LED matrix operation need to be started with this function.
     *  Scan line drawing by Ticker interrupt will be started.
     */
    void    start( void );

    /** Stop operation
     *
     *  This stops the operation.
     *  Ticker interrupt will be stopped
     */
    void    stop( void );

    /** Set the image to library internal buffer
     *
     *  8x8 pixel image will be copied into the library internal buffer.
     *  User don't need to care the timing of this function call because
     *  the library is using "ping-pong" buffering.
     *  This function writes data into in-active side of the buffer.
     *  The image will not be appear immediatly but from next scan start.
     *
     *  Each elements of the array should be brightness information
     *  in range of 0.0 to 1.0.
     *
     *  The 2 dimensional 8x8 array will be handled as..
     *
     *  p[0][0] : top-left
     *  p[0][7] : top-right
     *  p[7][0] : bottm-left
     *  p[7][7] : bottom-right
     *
     *  @param p image stored 2-dimensional float array
     */
    void    set_data( float p[ 8 ][ 8 ] );

private:
    I2C     *i2c_p;
    I2C     &i2c;
    char    address;                //  I2C slave address
    float   framerate;              //  frame rate in "Hz"
    int     in_operation;           //  ture, if scan is on-going
    int     line_counter;           //  counting scan line
    int     frame_counter;          //  counting frame number
    int     buffer_switch_request;  //  flag to switch the ping-pong buffer
    int     outgoing_buffer;        //  flag to select the buffer
    Ticker  t;
    char    pattern[ 2 ][ 8 ][ 8 ]; //  having 2 sets of 8x8 array for pin-pong buffering

    void    draw_a_line( void );    //  ISR called by Ticker
    void    initialize( void );     //  initialize function
};

#endif  //  MBED_PCA9622_LED8x8_H