InetrfaceProducts NXP / PCA9622_LED8x8

Dependents:   PCA9622_LED8x8_Demo PCA9622_LED8x8_Hello PCA9622_LED8x8_x6_Demo shake-shake-machine

Committer:
nxp_ip
Date:
Thu Dec 25 01:51:30 2014 +0000
Revision:
1:a1bf164ff73b
Parent:
0:41234a8149bd
Child:
2:cd00372373e4
multiple instance support (tested with 6 devices. default frame rate is changed to 50Hz)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nxp_ip 0:41234a8149bd 1 /**
nxp_ip 0:41234a8149bd 2 * PCA9622 LED 8x8 library
nxp_ip 0:41234a8149bd 3 *
nxp_ip 0:41234a8149bd 4 * @author Tedd OKANO
nxp_ip 0:41234a8149bd 5 * @version 1.0
nxp_ip 0:41234a8149bd 6 * @date 28-Nov-2014
nxp_ip 0:41234a8149bd 7 *
nxp_ip 0:41234a8149bd 8 * Library for "I2C 8x8 LED matrix board" from Switch Science
nxp_ip 0:41234a8149bd 9 * https://www.switch-science.com/catalog/2071/
nxp_ip 0:41234a8149bd 10 *
nxp_ip 0:41234a8149bd 11 * The I2C LED controller PCA9622 is used on this module
nxp_ip 0:41234a8149bd 12 * that ebables to control the LEDs with PWM brightness control.
nxp_ip 0:41234a8149bd 13 *
nxp_ip 0:41234a8149bd 14 * For more information about the PCA9622:
nxp_ip 0:41234a8149bd 15 * http://www.nxp.com/documents/data_sheet/PCA9622.pdf
nxp_ip 0:41234a8149bd 16 */
nxp_ip 0:41234a8149bd 17
nxp_ip 0:41234a8149bd 18 #include "mbed.h"
nxp_ip 0:41234a8149bd 19 #include "PCA9622_LED8x8.h"
nxp_ip 0:41234a8149bd 20
nxp_ip 0:41234a8149bd 21 PCA9622_LED8x8::PCA9622_LED8x8( PinName sda, PinName scl, char slave_adr, float fr )
nxp_ip 0:41234a8149bd 22 :
nxp_ip 0:41234a8149bd 23 i2c_p( new I2C( sda, scl ) ),
nxp_ip 0:41234a8149bd 24 i2c( *i2c_p ),
nxp_ip 0:41234a8149bd 25 address( slave_adr ),
nxp_ip 0:41234a8149bd 26 framerate( fr ),
nxp_ip 0:41234a8149bd 27 in_operation( false ),
nxp_ip 1:a1bf164ff73b 28 line_counter( 0 ),
nxp_ip 0:41234a8149bd 29 frame_counter( 0 ),
nxp_ip 0:41234a8149bd 30 buffer_switch_request( false ),
nxp_ip 0:41234a8149bd 31 outgoing_buffer( 0 )
nxp_ip 0:41234a8149bd 32 {
nxp_ip 0:41234a8149bd 33 initialize();
nxp_ip 0:41234a8149bd 34 }
nxp_ip 0:41234a8149bd 35
nxp_ip 0:41234a8149bd 36 PCA9622_LED8x8::PCA9622_LED8x8( I2C &i2c_obj, char slave_adr, float fr )
nxp_ip 0:41234a8149bd 37 :
nxp_ip 0:41234a8149bd 38 i2c_p( NULL ),
nxp_ip 0:41234a8149bd 39 i2c( i2c_obj ),
nxp_ip 0:41234a8149bd 40 address( slave_adr ),
nxp_ip 0:41234a8149bd 41 framerate( fr ),
nxp_ip 0:41234a8149bd 42 in_operation( false ),
nxp_ip 1:a1bf164ff73b 43 line_counter( 0 ),
nxp_ip 0:41234a8149bd 44 frame_counter( 0 ),
nxp_ip 0:41234a8149bd 45 buffer_switch_request( false ),
nxp_ip 0:41234a8149bd 46 outgoing_buffer( 0 )
nxp_ip 0:41234a8149bd 47 {
nxp_ip 0:41234a8149bd 48 initialize();
nxp_ip 0:41234a8149bd 49 }
nxp_ip 0:41234a8149bd 50
nxp_ip 0:41234a8149bd 51 PCA9622_LED8x8::~PCA9622_LED8x8()
nxp_ip 0:41234a8149bd 52 {
nxp_ip 0:41234a8149bd 53 }
nxp_ip 0:41234a8149bd 54
nxp_ip 0:41234a8149bd 55 void PCA9622_LED8x8::initialize( void )
nxp_ip 0:41234a8149bd 56 {
nxp_ip 0:41234a8149bd 57 char init[ 2 ][ 3 ] = {
nxp_ip 0:41234a8149bd 58 { 0x80, 0x00, 0x05 }, // initialize MODE1 and MODE2 registers
nxp_ip 0:41234a8149bd 59 { 0x96, 0xAA, 0xAA } // initialize LEDOUT2 and LEDOUT3 registers
nxp_ip 0:41234a8149bd 60 };
nxp_ip 0:41234a8149bd 61
nxp_ip 0:41234a8149bd 62 i2c.frequency( 400 * 1000 );
nxp_ip 0:41234a8149bd 63 i2c.write( address, init[ 0 ], sizeof( init[ 0 ] ) );
nxp_ip 0:41234a8149bd 64 i2c.write( address, init[ 1 ], sizeof( init[ 1 ] ) );
nxp_ip 1:a1bf164ff73b 65
nxp_ip 1:a1bf164ff73b 66 start();
nxp_ip 0:41234a8149bd 67 }
nxp_ip 0:41234a8149bd 68
nxp_ip 0:41234a8149bd 69 void PCA9622_LED8x8::frame_rate( float rate )
nxp_ip 0:41234a8149bd 70 {
nxp_ip 0:41234a8149bd 71 int previous_state;
nxp_ip 0:41234a8149bd 72
nxp_ip 0:41234a8149bd 73 previous_state = in_operation;
nxp_ip 0:41234a8149bd 74
nxp_ip 0:41234a8149bd 75 stop();
nxp_ip 0:41234a8149bd 76 framerate = rate;
nxp_ip 0:41234a8149bd 77
nxp_ip 0:41234a8149bd 78 if ( previous_state )
nxp_ip 0:41234a8149bd 79 start();
nxp_ip 0:41234a8149bd 80 }
nxp_ip 0:41234a8149bd 81
nxp_ip 0:41234a8149bd 82 void PCA9622_LED8x8::start( void )
nxp_ip 0:41234a8149bd 83 {
nxp_ip 0:41234a8149bd 84 t.attach( this, &PCA9622_LED8x8::draw_a_line, 1.0 / (framerate * 8.0) );
nxp_ip 0:41234a8149bd 85 in_operation = true;
nxp_ip 0:41234a8149bd 86 }
nxp_ip 0:41234a8149bd 87
nxp_ip 0:41234a8149bd 88 void PCA9622_LED8x8::stop( void )
nxp_ip 0:41234a8149bd 89 {
nxp_ip 0:41234a8149bd 90 t.detach();
nxp_ip 0:41234a8149bd 91 in_operation = false;
nxp_ip 0:41234a8149bd 92 }
nxp_ip 0:41234a8149bd 93
nxp_ip 0:41234a8149bd 94 void PCA9622_LED8x8::draw_a_line( void )
nxp_ip 0:41234a8149bd 95 {
nxp_ip 0:41234a8149bd 96 char write_data[ 13 ];
nxp_ip 0:41234a8149bd 97
nxp_ip 0:41234a8149bd 98 if ( buffer_switch_request && !line_counter ) {
nxp_ip 0:41234a8149bd 99 // when the scan start, and if the buffer switching is requested ping-pong bufer will be switched
nxp_ip 0:41234a8149bd 100 outgoing_buffer = !outgoing_buffer;
nxp_ip 0:41234a8149bd 101 buffer_switch_request = false;
nxp_ip 0:41234a8149bd 102 }
nxp_ip 0:41234a8149bd 103
nxp_ip 0:41234a8149bd 104 write_data[ 0 ] = 0x80 | 0xA; // pointing PWM8 register with increment flag
nxp_ip 0:41234a8149bd 105 // write_data[ 9 ] = 0x00; // don't need to stuff any data because this register will be ignored (because global PWM setting is not used)
nxp_ip 0:41234a8149bd 106 // write_data[ 10 ] = 0x00; // don't need to stuff any data because this register will be ignored (because global PWM setting is not used)
nxp_ip 0:41234a8149bd 107
nxp_ip 0:41234a8149bd 108 for ( int i = 0; i < 8; i++ )
nxp_ip 0:41234a8149bd 109 write_data[ i + 1 ] = pattern[ outgoing_buffer ][ line_counter ][ i ]; // PWM data are set to PWM8..PWM15 registers (driving ROW)
nxp_ip 0:41234a8149bd 110
nxp_ip 0:41234a8149bd 111 // A line below works fine on Cortex-M3 but not on Cortex-M0. So I needed to rewrite it
nxp_ip 0:41234a8149bd 112 // *((unsigned short *)(write_data + 11)) = 0x0001 << (line_counter << 1); // channel 0 to 7 are used to ON/OFF the column
nxp_ip 0:41234a8149bd 113
nxp_ip 0:41234a8149bd 114 // A line above is rewritten as next 3 lines
nxp_ip 0:41234a8149bd 115 unsigned short tmp = 0x0001 << (line_counter << 1);
nxp_ip 0:41234a8149bd 116 write_data[ 11 ] = tmp & 0xFF;
nxp_ip 0:41234a8149bd 117 write_data[ 12 ] = tmp >> 8;
nxp_ip 0:41234a8149bd 118
nxp_ip 0:41234a8149bd 119 i2c.write( address, write_data, sizeof( write_data ) ); // I2C transfer
nxp_ip 0:41234a8149bd 120
nxp_ip 0:41234a8149bd 121 line_counter = (line_counter + 1) & 0x7;
nxp_ip 0:41234a8149bd 122
nxp_ip 0:41234a8149bd 123 if ( line_counter )
nxp_ip 0:41234a8149bd 124 frame_counter++;
nxp_ip 0:41234a8149bd 125 }
nxp_ip 0:41234a8149bd 126
nxp_ip 0:41234a8149bd 127 void PCA9622_LED8x8::set_data( float p[ 8 ][ 8 ] )
nxp_ip 0:41234a8149bd 128 {
nxp_ip 0:41234a8149bd 129 for ( int i = 0; i < 8; i++ )
nxp_ip 0:41234a8149bd 130 for ( int j = 0; j < 8; j++ )
nxp_ip 0:41234a8149bd 131 pattern[ !outgoing_buffer /* store image to in-active side */ ][ i ][ 7 - j ] = (char)(p[ i ][ j ] * 255.0);
nxp_ip 0:41234a8149bd 132
nxp_ip 0:41234a8149bd 133 buffer_switch_request = true; // when the buffer filling done, raise this flag to switch the pin-pong buffer
nxp_ip 0:41234a8149bd 134 }