Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: PCA9622_LED8x8_Demo PCA9622_LED8x8_Hello PCA9622_LED8x8_x6_Demo shake-shake-machine
PCA9622_LED8x8.cpp@1:a1bf164ff73b, 2014-12-25 (annotated)
- 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?
| User | Revision | Line number | New 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 | } |
PCA9622 8x8 LED matrix module