gfdgd
Fork of PCA995xA by
PCA9955A/PCA9955A.cpp@0:a624e2eeccac, 2015-02-25 (annotated)
- Committer:
- nxp_ip
- Date:
- Wed Feb 25 06:42:41 2015 +0000
- Revision:
- 0:a624e2eeccac
- Child:
- 6:1c6e1af61981
Initial version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
nxp_ip | 0:a624e2eeccac | 1 | #include "mbed.h" |
nxp_ip | 0:a624e2eeccac | 2 | #include "PCA9955A.h" |
nxp_ip | 0:a624e2eeccac | 3 | |
nxp_ip | 0:a624e2eeccac | 4 | PCA9955A::PCA9955A( PinName i2c_sda, PinName i2c_scl, char i2c_address ) |
nxp_ip | 0:a624e2eeccac | 5 | : PCA995xA( i2c_sda, i2c_scl, i2c_address ), n_of_ports( 16 ) |
nxp_ip | 0:a624e2eeccac | 6 | { |
nxp_ip | 0:a624e2eeccac | 7 | initialize(); |
nxp_ip | 0:a624e2eeccac | 8 | } |
nxp_ip | 0:a624e2eeccac | 9 | |
nxp_ip | 0:a624e2eeccac | 10 | PCA9955A::PCA9955A( I2C &i2c_obj, char i2c_address ) |
nxp_ip | 0:a624e2eeccac | 11 | : PCA995xA( i2c_obj, i2c_address ), n_of_ports( 16 ) |
nxp_ip | 0:a624e2eeccac | 12 | { |
nxp_ip | 0:a624e2eeccac | 13 | initialize(); |
nxp_ip | 0:a624e2eeccac | 14 | } |
nxp_ip | 0:a624e2eeccac | 15 | |
nxp_ip | 0:a624e2eeccac | 16 | PCA9955A::~PCA9955A() |
nxp_ip | 0:a624e2eeccac | 17 | { |
nxp_ip | 0:a624e2eeccac | 18 | } |
nxp_ip | 0:a624e2eeccac | 19 | |
nxp_ip | 0:a624e2eeccac | 20 | void PCA9955A::initialize( void ) |
nxp_ip | 0:a624e2eeccac | 21 | { |
nxp_ip | 0:a624e2eeccac | 22 | char init_array[] = { |
nxp_ip | 0:a624e2eeccac | 23 | PCA995xA::AUTO_INCREMENT | REGISTER_START, // Command |
nxp_ip | 0:a624e2eeccac | 24 | 0x00, 0x00, // MODE1, MODE2 |
nxp_ip | 0:a624e2eeccac | 25 | 0xAA, 0xAA, 0xAA, 0xAA, // LEDOUT[3:0] |
nxp_ip | 0:a624e2eeccac | 26 | 0x80, 0x00, // GRPPWM, GRPFREQ |
nxp_ip | 0:a624e2eeccac | 27 | }; |
nxp_ip | 0:a624e2eeccac | 28 | |
nxp_ip | 0:a624e2eeccac | 29 | pwm( ALLPORTS, 0.0 ); |
nxp_ip | 0:a624e2eeccac | 30 | current( ALLPORTS, 0.1 ); |
nxp_ip | 0:a624e2eeccac | 31 | |
nxp_ip | 0:a624e2eeccac | 32 | write( init_array, sizeof( init_array ) ); |
nxp_ip | 0:a624e2eeccac | 33 | gradation_group_clear(); |
nxp_ip | 0:a624e2eeccac | 34 | } |
nxp_ip | 0:a624e2eeccac | 35 | |
nxp_ip | 0:a624e2eeccac | 36 | char PCA9955A::pwm_register_access( int port ) |
nxp_ip | 0:a624e2eeccac | 37 | { |
nxp_ip | 0:a624e2eeccac | 38 | if ( port < n_of_ports ) |
nxp_ip | 0:a624e2eeccac | 39 | return ( PWM_REGISTER_START + port ); |
nxp_ip | 0:a624e2eeccac | 40 | |
nxp_ip | 0:a624e2eeccac | 41 | return ( PWMALL ); |
nxp_ip | 0:a624e2eeccac | 42 | } |
nxp_ip | 0:a624e2eeccac | 43 | |
nxp_ip | 0:a624e2eeccac | 44 | char PCA9955A::current_register_access( int port ) |
nxp_ip | 0:a624e2eeccac | 45 | { |
nxp_ip | 0:a624e2eeccac | 46 | if ( port < n_of_ports ) |
nxp_ip | 0:a624e2eeccac | 47 | return ( IREF_REGISTER_START + port ); |
nxp_ip | 0:a624e2eeccac | 48 | |
nxp_ip | 0:a624e2eeccac | 49 | return ( IREFALL ); |
nxp_ip | 0:a624e2eeccac | 50 | } |
nxp_ip | 0:a624e2eeccac | 51 | |
nxp_ip | 0:a624e2eeccac | 52 | int PCA9955A::number_of_ports( void ) |
nxp_ip | 0:a624e2eeccac | 53 | { |
nxp_ip | 0:a624e2eeccac | 54 | return ( n_of_ports ); |
nxp_ip | 0:a624e2eeccac | 55 | } |
nxp_ip | 0:a624e2eeccac | 56 | |
nxp_ip | 0:a624e2eeccac | 57 | |
nxp_ip | 0:a624e2eeccac | 58 | char PCA9955A::gradation_group[ 16 ] = { 0xFF }; |
nxp_ip | 0:a624e2eeccac | 59 | |
nxp_ip | 0:a624e2eeccac | 60 | void PCA9955A::gradation_setting( int group, char ramp_rate, char step_time, char hold_cntl, char iref ) |
nxp_ip | 0:a624e2eeccac | 61 | { |
nxp_ip | 0:a624e2eeccac | 62 | char data[ 5 ] = { (RAMP_RATE_GRP0 + (group * GRAD_GROUP_OFFSET)) | AUTO_INCREMENT, |
nxp_ip | 0:a624e2eeccac | 63 | ramp_rate, |
nxp_ip | 0:a624e2eeccac | 64 | step_time, |
nxp_ip | 0:a624e2eeccac | 65 | hold_cntl, |
nxp_ip | 0:a624e2eeccac | 66 | iref |
nxp_ip | 0:a624e2eeccac | 67 | }; |
nxp_ip | 0:a624e2eeccac | 68 | |
nxp_ip | 0:a624e2eeccac | 69 | write( data, sizeof( data ) ); |
nxp_ip | 0:a624e2eeccac | 70 | } |
nxp_ip | 0:a624e2eeccac | 71 | |
nxp_ip | 0:a624e2eeccac | 72 | void PCA9955A::gradation_start( char group, char continuous_flag ) |
nxp_ip | 0:a624e2eeccac | 73 | { |
nxp_ip | 0:a624e2eeccac | 74 | static char v[] = { GRAD_CNTL, 0 }; |
nxp_ip | 0:a624e2eeccac | 75 | |
nxp_ip | 0:a624e2eeccac | 76 | v[ 1 ] = read( GRAD_CNTL ) | ((0x02 | continuous_flag) << (group * 2)); |
nxp_ip | 0:a624e2eeccac | 77 | // v[ 1 ] = ((0x02 | continuous_flag) << (group * 2)); |
nxp_ip | 0:a624e2eeccac | 78 | write( v, sizeof( v ) ); |
nxp_ip | 0:a624e2eeccac | 79 | } |
nxp_ip | 0:a624e2eeccac | 80 | |
nxp_ip | 0:a624e2eeccac | 81 | void PCA9955A::gradation_stop( void ) |
nxp_ip | 0:a624e2eeccac | 82 | { |
nxp_ip | 0:a624e2eeccac | 83 | char v[] = { GRAD_CNTL, 0 }; |
nxp_ip | 0:a624e2eeccac | 84 | |
nxp_ip | 0:a624e2eeccac | 85 | write( v, sizeof( v ) ); |
nxp_ip | 0:a624e2eeccac | 86 | } |
nxp_ip | 0:a624e2eeccac | 87 | |
nxp_ip | 0:a624e2eeccac | 88 | void PCA9955A::group_selector( short g0, short g1, short g2, short g3 ) |
nxp_ip | 0:a624e2eeccac | 89 | { |
nxp_ip | 0:a624e2eeccac | 90 | unsigned int pattern = 0x00000000; |
nxp_ip | 0:a624e2eeccac | 91 | short src[ 4 ]; |
nxp_ip | 0:a624e2eeccac | 92 | short port_select; |
nxp_ip | 0:a624e2eeccac | 93 | char v[ 7 ]; |
nxp_ip | 0:a624e2eeccac | 94 | int i; |
nxp_ip | 0:a624e2eeccac | 95 | int grp; |
nxp_ip | 0:a624e2eeccac | 96 | |
nxp_ip | 0:a624e2eeccac | 97 | v[ 0 ] = GRAD_MODE_SEL0 | AUTO_INCREMENT; |
nxp_ip | 0:a624e2eeccac | 98 | |
nxp_ip | 0:a624e2eeccac | 99 | port_select = g0 | g1 | g2 | g3; |
nxp_ip | 0:a624e2eeccac | 100 | v[ 1 ] = (port_select >> 0) & 0xFF; |
nxp_ip | 0:a624e2eeccac | 101 | v[ 2 ] = (port_select >> 8) & 0xFF; |
nxp_ip | 0:a624e2eeccac | 102 | |
nxp_ip | 0:a624e2eeccac | 103 | if ( 0x0000 == port_select ) { |
nxp_ip | 0:a624e2eeccac | 104 | write( v, 3 ); |
nxp_ip | 0:a624e2eeccac | 105 | return; |
nxp_ip | 0:a624e2eeccac | 106 | } |
nxp_ip | 0:a624e2eeccac | 107 | |
nxp_ip | 0:a624e2eeccac | 108 | src[ 0 ] = g0; |
nxp_ip | 0:a624e2eeccac | 109 | src[ 1 ] = g1; |
nxp_ip | 0:a624e2eeccac | 110 | src[ 2 ] = g2; |
nxp_ip | 0:a624e2eeccac | 111 | src[ 3 ] = g3; |
nxp_ip | 0:a624e2eeccac | 112 | |
nxp_ip | 0:a624e2eeccac | 113 | for ( i = 0; i < 16; i++ ) { |
nxp_ip | 0:a624e2eeccac | 114 | for ( grp = 0; grp < 4; grp++ ) { |
nxp_ip | 0:a624e2eeccac | 115 | if ( src[ grp ] & (0x1 << i) ) |
nxp_ip | 0:a624e2eeccac | 116 | pattern |= grp << (i * 2); |
nxp_ip | 0:a624e2eeccac | 117 | } |
nxp_ip | 0:a624e2eeccac | 118 | } |
nxp_ip | 0:a624e2eeccac | 119 | |
nxp_ip | 0:a624e2eeccac | 120 | for ( i = 0; i < 4; i++ ) |
nxp_ip | 0:a624e2eeccac | 121 | v[ i + 3 ] = 0xFF & (pattern >> (i * 8)); |
nxp_ip | 0:a624e2eeccac | 122 | |
nxp_ip | 0:a624e2eeccac | 123 | write( v, sizeof( v ) ); |
nxp_ip | 0:a624e2eeccac | 124 | } |
nxp_ip | 0:a624e2eeccac | 125 | |
nxp_ip | 0:a624e2eeccac | 126 | void PCA9955A::gradation_group_setting( char group, char port ) |
nxp_ip | 0:a624e2eeccac | 127 | { |
nxp_ip | 0:a624e2eeccac | 128 | short g[ 4 ] = { 0x0000 }; |
nxp_ip | 0:a624e2eeccac | 129 | |
nxp_ip | 0:a624e2eeccac | 130 | port &= 0xF; |
nxp_ip | 0:a624e2eeccac | 131 | gradation_group[ port ] = (group < 4) ? group : NOGROUP; |
nxp_ip | 0:a624e2eeccac | 132 | |
nxp_ip | 0:a624e2eeccac | 133 | for ( int i = 0; i < 16; i++ ) { |
nxp_ip | 0:a624e2eeccac | 134 | if ( gradation_group[ i ] != NOGROUP ) |
nxp_ip | 0:a624e2eeccac | 135 | g[ gradation_group[ i ] ] |= 0x0001 << i; |
nxp_ip | 0:a624e2eeccac | 136 | } |
nxp_ip | 0:a624e2eeccac | 137 | |
nxp_ip | 0:a624e2eeccac | 138 | group_selector( g[ 0 ], g[ 1 ], g[ 2 ], g[ 3 ] ); |
nxp_ip | 0:a624e2eeccac | 139 | // pwm( port, 1.0 ); |
nxp_ip | 0:a624e2eeccac | 140 | pwm( port, 0.3 ); |
nxp_ip | 0:a624e2eeccac | 141 | } |
nxp_ip | 0:a624e2eeccac | 142 | |
nxp_ip | 0:a624e2eeccac | 143 | void PCA9955A::gradation_group_clear( void ) |
nxp_ip | 0:a624e2eeccac | 144 | { |
nxp_ip | 0:a624e2eeccac | 145 | for ( int i = 0; i < 16; i++ ) { |
nxp_ip | 0:a624e2eeccac | 146 | gradation_group[ i ] = NOGROUP; |
nxp_ip | 0:a624e2eeccac | 147 | } |
nxp_ip | 0:a624e2eeccac | 148 | |
nxp_ip | 0:a624e2eeccac | 149 | group_selector( 0, 0, 0, 0 ); |
nxp_ip | 0:a624e2eeccac | 150 | } |
nxp_ip | 0:a624e2eeccac | 151 | |
nxp_ip | 0:a624e2eeccac | 152 | float PCA9955A::gradation_ramp_setting( char group, float cycle, char flag_on, char flag_off, int ramp_flag ) |
nxp_ip | 0:a624e2eeccac | 153 | { |
nxp_ip | 0:a624e2eeccac | 154 | int ramp_time; |
nxp_ip | 0:a624e2eeccac | 155 | char prescaler; |
nxp_ip | 0:a624e2eeccac | 156 | int required_steps; |
nxp_ip | 0:a624e2eeccac | 157 | char mult_factor; |
nxp_ip | 0:a624e2eeccac | 158 | char iref_inc; |
nxp_ip | 0:a624e2eeccac | 159 | int iref = 255; |
nxp_ip | 0:a624e2eeccac | 160 | |
nxp_ip | 0:a624e2eeccac | 161 | #define RAMP_RATE_GRP 1 |
nxp_ip | 0:a624e2eeccac | 162 | #define STEP_TIME_GRP 2 |
nxp_ip | 0:a624e2eeccac | 163 | #define HOLD_CNTL_GRP 3 |
nxp_ip | 0:a624e2eeccac | 164 | #define IREF_GRP 4 |
nxp_ip | 0:a624e2eeccac | 165 | |
nxp_ip | 0:a624e2eeccac | 166 | char regs[ 5 ]; |
nxp_ip | 0:a624e2eeccac | 167 | |
nxp_ip | 0:a624e2eeccac | 168 | float hold_time[] = { |
nxp_ip | 0:a624e2eeccac | 169 | 0.00, |
nxp_ip | 0:a624e2eeccac | 170 | 0.25, |
nxp_ip | 0:a624e2eeccac | 171 | 0.50, |
nxp_ip | 0:a624e2eeccac | 172 | 0.75, |
nxp_ip | 0:a624e2eeccac | 173 | 1.00, |
nxp_ip | 0:a624e2eeccac | 174 | 2.00, |
nxp_ip | 0:a624e2eeccac | 175 | 4.00, |
nxp_ip | 0:a624e2eeccac | 176 | 6.00 |
nxp_ip | 0:a624e2eeccac | 177 | }; |
nxp_ip | 0:a624e2eeccac | 178 | |
nxp_ip | 0:a624e2eeccac | 179 | |
nxp_ip | 0:a624e2eeccac | 180 | if ( ramp_flag == NO_RAMP ) { |
nxp_ip | 0:a624e2eeccac | 181 | iref_inc = 1; |
nxp_ip | 0:a624e2eeccac | 182 | ramp_time = 0; |
nxp_ip | 0:a624e2eeccac | 183 | prescaler = 0; |
nxp_ip | 0:a624e2eeccac | 184 | required_steps = 0; |
nxp_ip | 0:a624e2eeccac | 185 | mult_factor = 0; |
nxp_ip | 0:a624e2eeccac | 186 | } else { |
nxp_ip | 0:a624e2eeccac | 187 | ramp_time = (int)((cycle - (hold_time[ flag_on ] + hold_time[ flag_off ])) / ((ramp_flag == RAMP_UP_DOWN) ? 2.0 : 1.0) * 1000); |
nxp_ip | 0:a624e2eeccac | 188 | |
nxp_ip | 0:a624e2eeccac | 189 | prescaler = ( ramp_time <= 32 * (iref + 1)) ? 0 : 1; |
nxp_ip | 0:a624e2eeccac | 190 | |
nxp_ip | 0:a624e2eeccac | 191 | if ( prescaler ) |
nxp_ip | 0:a624e2eeccac | 192 | required_steps = ramp_time / 8; |
nxp_ip | 0:a624e2eeccac | 193 | else |
nxp_ip | 0:a624e2eeccac | 194 | required_steps = ramp_time * 2; |
nxp_ip | 0:a624e2eeccac | 195 | |
nxp_ip | 0:a624e2eeccac | 196 | if ( iref < required_steps ) { |
nxp_ip | 0:a624e2eeccac | 197 | iref_inc = 1; |
nxp_ip | 0:a624e2eeccac | 198 | mult_factor = required_steps / (iref + 1); |
nxp_ip | 0:a624e2eeccac | 199 | mult_factor = (mult_factor <= 0) ? 1 : mult_factor; |
nxp_ip | 0:a624e2eeccac | 200 | mult_factor = (64 < mult_factor) ? 64 : mult_factor; |
nxp_ip | 0:a624e2eeccac | 201 | } else { |
nxp_ip | 0:a624e2eeccac | 202 | iref_inc = (iref + 1) / required_steps; |
nxp_ip | 0:a624e2eeccac | 203 | iref_inc = (iref_inc <= 0) ? 1 : iref_inc; |
nxp_ip | 0:a624e2eeccac | 204 | iref_inc = (64 < iref_inc) ? 64 : iref_inc; |
nxp_ip | 0:a624e2eeccac | 205 | mult_factor = 1; |
nxp_ip | 0:a624e2eeccac | 206 | } |
nxp_ip | 0:a624e2eeccac | 207 | } |
nxp_ip | 0:a624e2eeccac | 208 | |
nxp_ip | 0:a624e2eeccac | 209 | // printf( "ramp_time=%d, required_steps=%d, iref=%d\r\n", ramp_time, required_steps, iref ); |
nxp_ip | 0:a624e2eeccac | 210 | // printf( "prescaler = %d, mult_factor=%d, iref_inc=%d\r\n", prescaler, mult_factor, iref_inc ); |
nxp_ip | 0:a624e2eeccac | 211 | // printf( "\r\n" ); |
nxp_ip | 0:a624e2eeccac | 212 | |
nxp_ip | 0:a624e2eeccac | 213 | regs[ 0 ] = 0x80 | (RAMP_RATE_GRP0 + (group * 4)); |
nxp_ip | 0:a624e2eeccac | 214 | regs[ RAMP_RATE_GRP ] = (ramp_flag << 6) | (iref_inc - 1); |
nxp_ip | 0:a624e2eeccac | 215 | regs[ STEP_TIME_GRP ] = (prescaler << 6) | (mult_factor - 1); |
nxp_ip | 0:a624e2eeccac | 216 | regs[ HOLD_CNTL_GRP ] = 0xC0 | (flag_on << 3) | flag_off; |
nxp_ip | 0:a624e2eeccac | 217 | regs[ IREF_GRP ] = iref; |
nxp_ip | 0:a624e2eeccac | 218 | |
nxp_ip | 0:a624e2eeccac | 219 | write( regs, sizeof( regs ) ); |
nxp_ip | 0:a624e2eeccac | 220 | |
nxp_ip | 0:a624e2eeccac | 221 | #if 0 |
nxp_ip | 0:a624e2eeccac | 222 | float n_of_steps; |
nxp_ip | 0:a624e2eeccac | 223 | float single_ramp_time; |
nxp_ip | 0:a624e2eeccac | 224 | float total_ramp_time; |
nxp_ip | 0:a624e2eeccac | 225 | |
nxp_ip | 0:a624e2eeccac | 226 | n_of_steps = (float)(((iref + 1) / iref_inc) * mult_factor); |
nxp_ip | 0:a624e2eeccac | 227 | single_ramp_time = n_of_steps * (prescaler ? 8.0 : 0.5); |
nxp_ip | 0:a624e2eeccac | 228 | total_ramp_time = single_ramp_time * ((ramp_flag == RAMP_UP_DOWN) ? 2.0 : 1.0); |
nxp_ip | 0:a624e2eeccac | 229 | printf( "n_of_steps = %f, single_ramp_time=%f, total_ramp_time=%f\r\n", n_of_steps, single_ramp_time, total_ramp_time ); |
nxp_ip | 0:a624e2eeccac | 230 | printf( "hold_time[ flag_on ] = %f, hold_time[ flag_off ]=%f\r\n", hold_time[ flag_on ], hold_time[ flag_off ] ); |
nxp_ip | 0:a624e2eeccac | 231 | #endif |
nxp_ip | 0:a624e2eeccac | 232 | |
nxp_ip | 0:a624e2eeccac | 233 | 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 ]) ); |
nxp_ip | 0:a624e2eeccac | 234 | } |
nxp_ip | 0:a624e2eeccac | 235 | |
nxp_ip | 0:a624e2eeccac | 236 | |
nxp_ip | 0:a624e2eeccac | 237 | void PCA9955A::dump_gradation_registers( void ) |
nxp_ip | 0:a624e2eeccac | 238 | { |
nxp_ip | 0:a624e2eeccac | 239 | char data[ 23 ]; |
nxp_ip | 0:a624e2eeccac | 240 | |
nxp_ip | 0:a624e2eeccac | 241 | read( RAMP_RATE_GRP0, data, sizeof( data ) ); |
nxp_ip | 0:a624e2eeccac | 242 | |
nxp_ip | 0:a624e2eeccac | 243 | printf( "GRAD_MODE_SEL[1|0] = 0x%02X%02X\r\n", data[ 17 ], data[ 16 ] ); |
nxp_ip | 0:a624e2eeccac | 244 | printf( "GRAD_GRP_SEL[3|2|1|0] = 0x%02X%02X%02X%02X\r\n", data[ 21 ], data[ 20 ], data[ 19 ], data[ 18 ] ); |
nxp_ip | 0:a624e2eeccac | 245 | printf( "GRAD_CNTL = 0x%02X\r\n", data[ 22 ] ); |
nxp_ip | 0:a624e2eeccac | 246 | printf( "RAMP_RATE = 0x%02X 0x%02X 0x%02X 0x%02X\r\n", data[ 0 ], data[ 4 ], data[ 8 ], data[ 12 ] ); |
nxp_ip | 0:a624e2eeccac | 247 | printf( "STEP_TIME = 0x%02X 0x%02X 0x%02X 0x%02X\r\n", data[ 1 ], data[ 5 ], data[ 9 ], data[ 13 ] ); |
nxp_ip | 0:a624e2eeccac | 248 | printf( "HOLD_CNTL = 0x%02X 0x%02X 0x%02X 0x%02X\r\n", data[ 2 ], data[ 6 ], data[ 10 ], data[ 14 ] ); |
nxp_ip | 0:a624e2eeccac | 249 | printf( "IREF = 0x%02X 0x%02X 0x%02X 0x%02X\r\n", data[ 3 ], data[ 7 ], data[ 11 ], data[ 15 ] ); |
nxp_ip | 0:a624e2eeccac | 250 | printf( "\r\n" ); |
nxp_ip | 0:a624e2eeccac | 251 | } |