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: PCA9956A_Hello pca9956b_two_demoboards PCA9955A_Gradation_control PCA9955A_Gradation_control ... more
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 }
Generated on Wed Jul 13 2022 08:07:57 by
