InetrfaceProducts NXP / PCA995xA

Dependencies:   CompLedDvrCC

Dependents:   PCA9956A_Hello pca9956b_two_demoboards PCA9955A_Gradation_control PCA9955A_Gradation_control ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PCA9955A.cpp Source File

PCA9955A.cpp

00001 #include    "mbed.h"
00002 #include    "PCA9955A.h"
00003 
00004 PCA9955A::PCA9955A( PinName i2c_sda, PinName i2c_scl, char i2c_address )
00005     : PCA995xA( i2c_sda, i2c_scl, i2c_address ), n_of_ports( 16 )
00006 {
00007     initialize();
00008 }
00009 
00010 PCA9955A::PCA9955A( I2C &i2c_obj, char i2c_address )
00011     : PCA995xA( i2c_obj, i2c_address ), n_of_ports( 16 )
00012 {
00013     initialize();
00014 }
00015 
00016 PCA9955A::~PCA9955A()
00017 {
00018 }
00019 
00020 void PCA9955A::initialize( void )
00021 {
00022     char init_array[] = {
00023         PCA995xA::AUTO_INCREMENT | REGISTER_START,  //  Command
00024         0x00, 0x00,                                 //  MODE1, MODE2
00025         0xAA, 0xAA, 0xAA, 0xAA,                     //  LEDOUT[3:0]
00026         0x80, 0x00,                                 //  GRPPWM, GRPFREQ
00027     };
00028 
00029     pwm( ALLPORTS, 0.0 );    
00030     current( ALLPORTS, 0.1 );    
00031 
00032     write( init_array, sizeof( init_array ) );
00033     gradation_group_clear();
00034 }
00035 
00036 char PCA9955A::pwm_register_access( int port )
00037 {
00038     if ( port < n_of_ports )
00039         return ( PWM_REGISTER_START + port );
00040 
00041     return ( PWMALL );
00042 }
00043 
00044 char PCA9955A::current_register_access( int port )
00045 {
00046     if ( port < n_of_ports )
00047         return ( IREF_REGISTER_START + port );
00048 
00049     return ( IREFALL );
00050 }
00051 
00052 int PCA9955A::number_of_ports( void )
00053 {
00054     return ( n_of_ports );
00055 }
00056 
00057 
00058 char  PCA9955A::gradation_group[ 16 ] = { 0xFF };
00059 
00060 void PCA9955A::gradation_setting( int group, char ramp_rate, char step_time, char hold_cntl, char iref )
00061 {
00062     char    data[ 5 ]   = { (RAMP_RATE_GRP0 + (group * GRAD_GROUP_OFFSET)) | AUTO_INCREMENT,
00063                             ramp_rate,
00064                             step_time,
00065                             hold_cntl,
00066                             iref
00067                           };
00068 
00069     write( data, sizeof( data ) );
00070 }
00071 
00072 void PCA9955A::gradation_start( char group, char continuous_flag )
00073 {
00074     static char v[]   = { GRAD_CNTL, 0 };
00075     char        rd;
00076     
00077     rd      = read( GRAD_CNTL ) & ~(0x3 << (group * 2));
00078     
00079     printf( "rd = 0x%02X\r\n", rd );
00080     v[ 1 ]  = rd | ((0x02 | continuous_flag) << (group * 2));
00081 //    v[ 1 ]  = ((0x02 | continuous_flag) << (group * 2));
00082     write( v, sizeof( v ) );
00083 }
00084 
00085 void PCA9955A::gradation_stop( void )
00086 {
00087     char    v[]   = { GRAD_CNTL, 0 };
00088 
00089     write( v, sizeof( v ) );
00090 }
00091 
00092 void PCA9955A::group_selector( short g0, short g1, short g2, short g3 )
00093 {
00094     unsigned int    pattern = 0x00000000;
00095     short           src[ 4 ];
00096     short           port_select;
00097     char            v[ 7 ];
00098     int             i;
00099     int             grp;
00100 
00101     v[ 0 ]  = GRAD_MODE_SEL0 | AUTO_INCREMENT;
00102 
00103     port_select = g0 | g1 | g2 | g3;
00104     v[ 1 ]  = (port_select >> 0) & 0xFF;
00105     v[ 2 ]  = (port_select >> 8) & 0xFF;
00106 
00107     if ( 0x0000 == port_select ) {
00108         write( v, 3 );
00109         return;
00110     }
00111 
00112     src[ 0 ]    = g0;
00113     src[ 1 ]    = g1;
00114     src[ 2 ]    = g2;
00115     src[ 3 ]    = g3;
00116 
00117     for ( i = 0; i < 16; i++ ) {
00118         for ( grp = 0; grp < 4; grp++ ) {
00119             if ( src[ grp ] & (0x1 << i) )
00120                 pattern |= grp << (i * 2);
00121         }
00122     }
00123 
00124     for ( i = 0; i < 4; i++ )
00125         v[ i + 3 ]  = 0xFF & (pattern >>  (i * 8));
00126 
00127     write( v, sizeof( v ) );
00128 }
00129 
00130 void PCA9955A::gradation_group_setting( char group, char port )
00131 {
00132     short   g[ 4 ]  = { 0x0000 };
00133 
00134     port    &= 0xF;
00135     gradation_group[ port ] = (group < 4) ? group : NOGROUP;
00136 
00137     for ( int i = 0; i < 16; i++ ) {
00138         if ( gradation_group[ i ] != NOGROUP )
00139             g[ gradation_group[ i ] ]  |= 0x0001 << i;
00140     }
00141 
00142     group_selector( g[ 0 ], g[ 1 ], g[ 2 ], g[ 3 ] );
00143 //    pwm( port, 1.0 );
00144     pwm( port, 0.3 );
00145 }
00146 
00147 void PCA9955A::gradation_group_clear( void )
00148 {
00149     for ( int i = 0; i < 16; i++ ) {
00150         gradation_group[ i ] = NOGROUP;
00151     }
00152 
00153     group_selector( 0, 0, 0, 0 );
00154 }
00155 
00156 float PCA9955A::gradation_ramp_setting( char group, float cycle, char flag_on, char flag_off, int ramp_flag )
00157 {
00158     int     ramp_time;
00159     char    prescaler;
00160     int     required_steps;
00161     char    mult_factor;
00162     char    iref_inc;
00163     int     iref        = 255;
00164 
00165 #define     RAMP_RATE_GRP   1
00166 #define     STEP_TIME_GRP   2
00167 #define     HOLD_CNTL_GRP   3
00168 #define     IREF_GRP        4
00169 
00170     char    regs[ 5 ];
00171 
00172     float hold_time[]   = {
00173         0.00,
00174         0.25,
00175         0.50,
00176         0.75,
00177         1.00,
00178         2.00,
00179         4.00,
00180         6.00
00181     };
00182 
00183 
00184     if ( ramp_flag == NO_RAMP ) {
00185         iref_inc        = 1;
00186         ramp_time       = 0;
00187         prescaler       = 0;
00188         required_steps  = 0;
00189         mult_factor     = 0;
00190     } else {
00191         ramp_time   = (int)((cycle - (hold_time[ flag_on ] + hold_time[ flag_off ])) / ((ramp_flag == RAMP_UP_DOWN) ? 2.0 : 1.0) * 1000);
00192 
00193         prescaler       = ( ramp_time <= 32 * (iref + 1)) ? 0 : 1;
00194 
00195         if ( prescaler )
00196             required_steps  = ramp_time / 8;
00197         else
00198             required_steps  = ramp_time * 2;
00199 
00200         if ( iref < required_steps ) {
00201             iref_inc    = 1;
00202             mult_factor = required_steps / (iref + 1);
00203             mult_factor = (mult_factor <= 0) ?  1 : mult_factor;
00204             mult_factor = (64 < mult_factor) ? 64 : mult_factor;
00205         } else {
00206             iref_inc    = (iref + 1) / required_steps;
00207             iref_inc    = (iref_inc <= 0) ?  1 : iref_inc;
00208             iref_inc    = (64 < iref_inc) ? 64 : iref_inc;
00209             mult_factor = 1;
00210         }
00211     }
00212 
00213 //    printf( "ramp_time=%d, required_steps=%d, iref=%d\r\n", ramp_time, required_steps, iref );
00214 //    printf( "prescaler = %d, mult_factor=%d, iref_inc=%d\r\n", prescaler, mult_factor, iref_inc );
00215 //    printf( "\r\n" );
00216 
00217     regs[ 0             ]   = 0x80 | (RAMP_RATE_GRP0 + (group * 4));
00218     regs[ RAMP_RATE_GRP ]   = (ramp_flag << 6) | (iref_inc - 1);
00219     regs[ STEP_TIME_GRP ]   = (prescaler << 6) | (mult_factor - 1);
00220     regs[ HOLD_CNTL_GRP ]   = 0xC0 | (flag_on << 3) | flag_off;
00221     regs[ IREF_GRP      ]   = iref;
00222 
00223     write( regs, sizeof( regs ) );
00224     
00225 #if 0
00226     float   n_of_steps;
00227     float   single_ramp_time;
00228     float   total_ramp_time;
00229     
00230     n_of_steps          = (float)(((iref + 1) / iref_inc) * mult_factor);
00231     single_ramp_time    = n_of_steps * (prescaler ? 8.0 : 0.5);
00232     total_ramp_time     = single_ramp_time * ((ramp_flag == RAMP_UP_DOWN) ? 2.0 : 1.0);
00233     printf( "n_of_steps = %f, single_ramp_time=%f, total_ramp_time=%f\r\n", n_of_steps, single_ramp_time, total_ramp_time );
00234     printf( "hold_time[ flag_on ] = %f, hold_time[ flag_off ]=%f\r\n", hold_time[ flag_on ], hold_time[ flag_off ] );
00235 #endif
00236 
00237     return ( (((((float)(((iref + 1) / iref_inc) * mult_factor)) * (prescaler ? 8.0 : 0.5)) * ((ramp_flag == RAMP_UP_DOWN) ? 2.0 : 1.0)) ) * 0.001 + (hold_time[ flag_on ] + hold_time[ flag_off ]) );
00238 }
00239 
00240 
00241 void PCA9955A::dump_gradation_registers( void )
00242 {
00243     char    data[ 23 ];
00244 
00245     read( RAMP_RATE_GRP0, data, sizeof( data ) );
00246 
00247     printf( "GRAD_MODE_SEL[1|0]     = 0x%02X%02X\r\n", data[ 17 ], data[ 16 ] );
00248     printf( "GRAD_GRP_SEL[3|2|1|0]  = 0x%02X%02X%02X%02X\r\n", data[ 21 ], data[ 20 ], data[ 19 ], data[ 18 ] );
00249     printf( "GRAD_CNTL      = 0x%02X\r\n", data[ 22 ] );
00250     printf( "RAMP_RATE  =  0x%02X  0x%02X  0x%02X  0x%02X\r\n", data[ 0 ], data[ 4 ], data[ 8 ], data[ 12 ] );
00251     printf( "STEP_TIME  =  0x%02X  0x%02X  0x%02X  0x%02X\r\n", data[ 1 ], data[ 5 ], data[ 9 ], data[ 13 ] );
00252     printf( "HOLD_CNTL  =  0x%02X  0x%02X  0x%02X  0x%02X\r\n", data[ 2 ], data[ 6 ], data[ 10 ], data[ 14 ] );
00253     printf( "IREF       =  0x%02X  0x%02X  0x%02X  0x%02X\r\n", data[ 3 ], data[ 7 ], data[ 11 ], data[ 15 ] );
00254     printf( "\r\n" );
00255 }