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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PCA9622_LED8x8.cpp Source File

PCA9622_LED8x8.cpp

00001 /**
00002  *  PCA9622 LED 8x8 library
00003  *
00004  *  @author  Tedd OKANO
00005  *  @version 1.1.1
00006  *  @date    26-Feb-2015
00007  *
00008  *  Library for "I2C 8x8 LED matrix board" from Switch Science
00009  *    https://www.switch-science.com/catalog/2071/
00010  *
00011  *  The I2C LED controller PCA9622 is used on this module 
00012  *  that ebables to control the LEDs with PWM brightness control. 
00013  *  
00014  *  For more information about the PCA9622:
00015  *    http://www.nxp.com/documents/data_sheet/PCA9622.pdf
00016  */
00017 
00018 #include    "mbed.h"
00019 #include    "PCA9622_LED8x8.h"
00020 
00021 PCA9622_LED8x8::PCA9622_LED8x8( PinName sda, PinName scl, char slave_adr, float fr )
00022     :
00023     i2c_p( new I2C( sda, scl ) ), 
00024     i2c( *i2c_p ), 
00025     address( slave_adr ),
00026     framerate( fr ),
00027     in_operation( false ),
00028     line_counter( 0 ),
00029     frame_counter( 0 ),
00030     buffer_switch_request( false ),
00031     outgoing_buffer( 0 )
00032 {
00033     initialize();
00034 }
00035 
00036 PCA9622_LED8x8::PCA9622_LED8x8( I2C &i2c_obj, char slave_adr, float fr )
00037     :
00038     i2c_p( NULL ), 
00039     i2c( i2c_obj ),
00040     address( slave_adr ),
00041     framerate( fr ),
00042     in_operation( false ),
00043     line_counter( 0 ),
00044     frame_counter( 0 ),
00045     buffer_switch_request( false ),
00046     outgoing_buffer( 0 )
00047 {
00048     initialize();
00049 }
00050 
00051 PCA9622_LED8x8::~PCA9622_LED8x8()
00052 {
00053     if ( NULL != i2c_p )
00054         delete  i2c_p;
00055 }
00056 
00057 void PCA9622_LED8x8::initialize( void )
00058 {
00059     char    init[ 2 ][ 3 ]   = {
00060         { 0x80, 0x00, 0x05 },   //  initialize MODE1 and MODE2 registers
00061         { 0x96, 0xAA, 0xAA }    //  initialize LEDOUT2 and LEDOUT3 registers
00062     };
00063 
00064     i2c.frequency( 400 * 1000 );
00065     i2c.write( address, init[ 0 ], sizeof( init[ 0 ] ) );
00066     i2c.write( address, init[ 1 ], sizeof( init[ 1 ] ) );
00067     
00068     start();
00069 }
00070 
00071 void PCA9622_LED8x8::frame_rate( float rate )
00072 {
00073     int     previous_state;
00074 
00075     previous_state  = in_operation;
00076 
00077     stop();
00078     framerate  = rate;
00079 
00080     if ( previous_state )
00081         start();
00082 }
00083 
00084 void PCA9622_LED8x8::start( void )
00085 {
00086     t.attach( this, &PCA9622_LED8x8::draw_a_line, 1.0 / (framerate * 8.0) );
00087     in_operation    = true;
00088 }
00089 
00090 void PCA9622_LED8x8::stop( void )
00091 {
00092     t.detach();
00093     in_operation    = false;
00094 }
00095 
00096 void PCA9622_LED8x8::draw_a_line( void )
00097 {
00098     char        write_data[ 13 ];
00099 
00100     if ( buffer_switch_request && !line_counter ) {
00101         //  when the scan start, and if the buffer switching is requested ping-pong bufer will be switched
00102         outgoing_buffer         = !outgoing_buffer;
00103         buffer_switch_request   = false;
00104     }
00105 
00106     write_data[  0 ]    = 0x80 | 0xA;   //  pointing PWM8 register with increment flag 
00107     //  write_data[  9 ]    = 0x00;     //  don't need to stuff any data because this register will be ignored (because global PWM setting is not used)
00108     //  write_data[ 10 ]    = 0x00;     //  don't need to stuff any data because this register will be ignored (because global PWM setting is not used)
00109 
00110     for ( int i = 0; i < 8; i++ )
00111         write_data[ i + 1 ]   = pattern[ outgoing_buffer ][ line_counter ][ i ];    //  PWM data are set to PWM8..PWM15 registers (driving ROW)
00112 
00113     //  A line below works fine on Cortex-M3 but not on Cortex-M0. So I needed to rewrite it
00114     //  *((unsigned short *)(write_data + 11))  = 0x0001 << (line_counter << 1);    //  channel 0 to 7 are used to ON/OFF the column
00115 
00116     //  A line above is rewritten as next 3 lines
00117     unsigned short  tmp     = 0x0001 << (line_counter << 1);
00118     write_data[ 11 ]    = tmp &  0xFF;
00119     write_data[ 12 ]    = tmp >> 8;
00120 
00121     i2c.write( address, write_data, sizeof( write_data ) );     //  I2C transfer
00122 
00123     line_counter    = (line_counter + 1) & 0x7;
00124 
00125     if ( line_counter )
00126         frame_counter++;
00127 }
00128 
00129 void PCA9622_LED8x8::set_data( float p[ 8 ][ 8 ] )
00130 {
00131     for ( int i = 0; i < 8; i++ )
00132         for ( int j = 0; j < 8; j++ )
00133             pattern[ !outgoing_buffer /* store image to in-active side */ ][ i ][ 7 - j ]   = (char)(p[ i ][ j ] * 255.0);
00134 
00135     buffer_switch_request   = true; //  when the buffer filling done, raise this flag to switch the pin-pong buffer
00136 }