gfdgd
Fork of PCA995xA by
PCA9955A/PCA9955A.cpp@6:1c6e1af61981, 2015-10-31 (annotated)
- Committer:
- okano
- Date:
- Sat Oct 31 06:07:15 2015 +0000
- Revision:
- 6:1c6e1af61981
- Parent:
- 0:a624e2eeccac
- Child:
- 7:56a45c690801
fix for single shot gradation start
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 }; |
okano | 6:1c6e1af61981 | 75 | char rd; |
okano | 6:1c6e1af61981 | 76 | |
okano | 6:1c6e1af61981 | 77 | rd = read( GRAD_CNTL ) & ~(0x3 << (group * 2)); |
okano | 6:1c6e1af61981 | 78 | |
okano | 6:1c6e1af61981 | 79 | printf( "rd = 0x%02X\r\n", rd ); |
okano | 6:1c6e1af61981 | 80 | v[ 1 ] = rd | ((0x02 | continuous_flag) << (group * 2)); |
nxp_ip | 0:a624e2eeccac | 81 | // v[ 1 ] = ((0x02 | continuous_flag) << (group * 2)); |
nxp_ip | 0:a624e2eeccac | 82 | write( v, sizeof( v ) ); |
nxp_ip | 0:a624e2eeccac | 83 | } |
nxp_ip | 0:a624e2eeccac | 84 | |
nxp_ip | 0:a624e2eeccac | 85 | void PCA9955A::gradation_stop( void ) |
nxp_ip | 0:a624e2eeccac | 86 | { |
nxp_ip | 0:a624e2eeccac | 87 | char v[] = { GRAD_CNTL, 0 }; |
nxp_ip | 0:a624e2eeccac | 88 | |
nxp_ip | 0:a624e2eeccac | 89 | write( v, sizeof( v ) ); |
nxp_ip | 0:a624e2eeccac | 90 | } |
nxp_ip | 0:a624e2eeccac | 91 | |
nxp_ip | 0:a624e2eeccac | 92 | void PCA9955A::group_selector( short g0, short g1, short g2, short g3 ) |
nxp_ip | 0:a624e2eeccac | 93 | { |
nxp_ip | 0:a624e2eeccac | 94 | unsigned int pattern = 0x00000000; |
nxp_ip | 0:a624e2eeccac | 95 | short src[ 4 ]; |
nxp_ip | 0:a624e2eeccac | 96 | short port_select; |
nxp_ip | 0:a624e2eeccac | 97 | char v[ 7 ]; |
nxp_ip | 0:a624e2eeccac | 98 | int i; |
nxp_ip | 0:a624e2eeccac | 99 | int grp; |
nxp_ip | 0:a624e2eeccac | 100 | |
nxp_ip | 0:a624e2eeccac | 101 | v[ 0 ] = GRAD_MODE_SEL0 | AUTO_INCREMENT; |
nxp_ip | 0:a624e2eeccac | 102 | |
nxp_ip | 0:a624e2eeccac | 103 | port_select = g0 | g1 | g2 | g3; |
nxp_ip | 0:a624e2eeccac | 104 | v[ 1 ] = (port_select >> 0) & 0xFF; |
nxp_ip | 0:a624e2eeccac | 105 | v[ 2 ] = (port_select >> 8) & 0xFF; |
nxp_ip | 0:a624e2eeccac | 106 | |
nxp_ip | 0:a624e2eeccac | 107 | if ( 0x0000 == port_select ) { |
nxp_ip | 0:a624e2eeccac | 108 | write( v, 3 ); |
nxp_ip | 0:a624e2eeccac | 109 | return; |
nxp_ip | 0:a624e2eeccac | 110 | } |
nxp_ip | 0:a624e2eeccac | 111 | |
nxp_ip | 0:a624e2eeccac | 112 | src[ 0 ] = g0; |
nxp_ip | 0:a624e2eeccac | 113 | src[ 1 ] = g1; |
nxp_ip | 0:a624e2eeccac | 114 | src[ 2 ] = g2; |
nxp_ip | 0:a624e2eeccac | 115 | src[ 3 ] = g3; |
nxp_ip | 0:a624e2eeccac | 116 | |
nxp_ip | 0:a624e2eeccac | 117 | for ( i = 0; i < 16; i++ ) { |
nxp_ip | 0:a624e2eeccac | 118 | for ( grp = 0; grp < 4; grp++ ) { |
nxp_ip | 0:a624e2eeccac | 119 | if ( src[ grp ] & (0x1 << i) ) |
nxp_ip | 0:a624e2eeccac | 120 | pattern |= grp << (i * 2); |
nxp_ip | 0:a624e2eeccac | 121 | } |
nxp_ip | 0:a624e2eeccac | 122 | } |
nxp_ip | 0:a624e2eeccac | 123 | |
nxp_ip | 0:a624e2eeccac | 124 | for ( i = 0; i < 4; i++ ) |
nxp_ip | 0:a624e2eeccac | 125 | v[ i + 3 ] = 0xFF & (pattern >> (i * 8)); |
nxp_ip | 0:a624e2eeccac | 126 | |
nxp_ip | 0:a624e2eeccac | 127 | write( v, sizeof( v ) ); |
nxp_ip | 0:a624e2eeccac | 128 | } |
nxp_ip | 0:a624e2eeccac | 129 | |
nxp_ip | 0:a624e2eeccac | 130 | void PCA9955A::gradation_group_setting( char group, char port ) |
nxp_ip | 0:a624e2eeccac | 131 | { |
nxp_ip | 0:a624e2eeccac | 132 | short g[ 4 ] = { 0x0000 }; |
nxp_ip | 0:a624e2eeccac | 133 | |
nxp_ip | 0:a624e2eeccac | 134 | port &= 0xF; |
nxp_ip | 0:a624e2eeccac | 135 | gradation_group[ port ] = (group < 4) ? group : NOGROUP; |
nxp_ip | 0:a624e2eeccac | 136 | |
nxp_ip | 0:a624e2eeccac | 137 | for ( int i = 0; i < 16; i++ ) { |
nxp_ip | 0:a624e2eeccac | 138 | if ( gradation_group[ i ] != NOGROUP ) |
nxp_ip | 0:a624e2eeccac | 139 | g[ gradation_group[ i ] ] |= 0x0001 << i; |
nxp_ip | 0:a624e2eeccac | 140 | } |
nxp_ip | 0:a624e2eeccac | 141 | |
nxp_ip | 0:a624e2eeccac | 142 | group_selector( g[ 0 ], g[ 1 ], g[ 2 ], g[ 3 ] ); |
nxp_ip | 0:a624e2eeccac | 143 | // pwm( port, 1.0 ); |
nxp_ip | 0:a624e2eeccac | 144 | pwm( port, 0.3 ); |
nxp_ip | 0:a624e2eeccac | 145 | } |
nxp_ip | 0:a624e2eeccac | 146 | |
nxp_ip | 0:a624e2eeccac | 147 | void PCA9955A::gradation_group_clear( void ) |
nxp_ip | 0:a624e2eeccac | 148 | { |
nxp_ip | 0:a624e2eeccac | 149 | for ( int i = 0; i < 16; i++ ) { |
nxp_ip | 0:a624e2eeccac | 150 | gradation_group[ i ] = NOGROUP; |
nxp_ip | 0:a624e2eeccac | 151 | } |
nxp_ip | 0:a624e2eeccac | 152 | |
nxp_ip | 0:a624e2eeccac | 153 | group_selector( 0, 0, 0, 0 ); |
nxp_ip | 0:a624e2eeccac | 154 | } |
nxp_ip | 0:a624e2eeccac | 155 | |
nxp_ip | 0:a624e2eeccac | 156 | float PCA9955A::gradation_ramp_setting( char group, float cycle, char flag_on, char flag_off, int ramp_flag ) |
nxp_ip | 0:a624e2eeccac | 157 | { |
nxp_ip | 0:a624e2eeccac | 158 | int ramp_time; |
nxp_ip | 0:a624e2eeccac | 159 | char prescaler; |
nxp_ip | 0:a624e2eeccac | 160 | int required_steps; |
nxp_ip | 0:a624e2eeccac | 161 | char mult_factor; |
nxp_ip | 0:a624e2eeccac | 162 | char iref_inc; |
nxp_ip | 0:a624e2eeccac | 163 | int iref = 255; |
nxp_ip | 0:a624e2eeccac | 164 | |
nxp_ip | 0:a624e2eeccac | 165 | #define RAMP_RATE_GRP 1 |
nxp_ip | 0:a624e2eeccac | 166 | #define STEP_TIME_GRP 2 |
nxp_ip | 0:a624e2eeccac | 167 | #define HOLD_CNTL_GRP 3 |
nxp_ip | 0:a624e2eeccac | 168 | #define IREF_GRP 4 |
nxp_ip | 0:a624e2eeccac | 169 | |
nxp_ip | 0:a624e2eeccac | 170 | char regs[ 5 ]; |
nxp_ip | 0:a624e2eeccac | 171 | |
nxp_ip | 0:a624e2eeccac | 172 | float hold_time[] = { |
nxp_ip | 0:a624e2eeccac | 173 | 0.00, |
nxp_ip | 0:a624e2eeccac | 174 | 0.25, |
nxp_ip | 0:a624e2eeccac | 175 | 0.50, |
nxp_ip | 0:a624e2eeccac | 176 | 0.75, |
nxp_ip | 0:a624e2eeccac | 177 | 1.00, |
nxp_ip | 0:a624e2eeccac | 178 | 2.00, |
nxp_ip | 0:a624e2eeccac | 179 | 4.00, |
nxp_ip | 0:a624e2eeccac | 180 | 6.00 |
nxp_ip | 0:a624e2eeccac | 181 | }; |
nxp_ip | 0:a624e2eeccac | 182 | |
nxp_ip | 0:a624e2eeccac | 183 | |
nxp_ip | 0:a624e2eeccac | 184 | if ( ramp_flag == NO_RAMP ) { |
nxp_ip | 0:a624e2eeccac | 185 | iref_inc = 1; |
nxp_ip | 0:a624e2eeccac | 186 | ramp_time = 0; |
nxp_ip | 0:a624e2eeccac | 187 | prescaler = 0; |
nxp_ip | 0:a624e2eeccac | 188 | required_steps = 0; |
nxp_ip | 0:a624e2eeccac | 189 | mult_factor = 0; |
nxp_ip | 0:a624e2eeccac | 190 | } else { |
nxp_ip | 0:a624e2eeccac | 191 | 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 | 192 | |
nxp_ip | 0:a624e2eeccac | 193 | prescaler = ( ramp_time <= 32 * (iref + 1)) ? 0 : 1; |
nxp_ip | 0:a624e2eeccac | 194 | |
nxp_ip | 0:a624e2eeccac | 195 | if ( prescaler ) |
nxp_ip | 0:a624e2eeccac | 196 | required_steps = ramp_time / 8; |
nxp_ip | 0:a624e2eeccac | 197 | else |
nxp_ip | 0:a624e2eeccac | 198 | required_steps = ramp_time * 2; |
nxp_ip | 0:a624e2eeccac | 199 | |
nxp_ip | 0:a624e2eeccac | 200 | if ( iref < required_steps ) { |
nxp_ip | 0:a624e2eeccac | 201 | iref_inc = 1; |
nxp_ip | 0:a624e2eeccac | 202 | mult_factor = required_steps / (iref + 1); |
nxp_ip | 0:a624e2eeccac | 203 | mult_factor = (mult_factor <= 0) ? 1 : mult_factor; |
nxp_ip | 0:a624e2eeccac | 204 | mult_factor = (64 < mult_factor) ? 64 : mult_factor; |
nxp_ip | 0:a624e2eeccac | 205 | } else { |
nxp_ip | 0:a624e2eeccac | 206 | iref_inc = (iref + 1) / required_steps; |
nxp_ip | 0:a624e2eeccac | 207 | iref_inc = (iref_inc <= 0) ? 1 : iref_inc; |
nxp_ip | 0:a624e2eeccac | 208 | iref_inc = (64 < iref_inc) ? 64 : iref_inc; |
nxp_ip | 0:a624e2eeccac | 209 | mult_factor = 1; |
nxp_ip | 0:a624e2eeccac | 210 | } |
nxp_ip | 0:a624e2eeccac | 211 | } |
nxp_ip | 0:a624e2eeccac | 212 | |
nxp_ip | 0:a624e2eeccac | 213 | // printf( "ramp_time=%d, required_steps=%d, iref=%d\r\n", ramp_time, required_steps, iref ); |
nxp_ip | 0:a624e2eeccac | 214 | // printf( "prescaler = %d, mult_factor=%d, iref_inc=%d\r\n", prescaler, mult_factor, iref_inc ); |
nxp_ip | 0:a624e2eeccac | 215 | // printf( "\r\n" ); |
nxp_ip | 0:a624e2eeccac | 216 | |
nxp_ip | 0:a624e2eeccac | 217 | regs[ 0 ] = 0x80 | (RAMP_RATE_GRP0 + (group * 4)); |
nxp_ip | 0:a624e2eeccac | 218 | regs[ RAMP_RATE_GRP ] = (ramp_flag << 6) | (iref_inc - 1); |
nxp_ip | 0:a624e2eeccac | 219 | regs[ STEP_TIME_GRP ] = (prescaler << 6) | (mult_factor - 1); |
nxp_ip | 0:a624e2eeccac | 220 | regs[ HOLD_CNTL_GRP ] = 0xC0 | (flag_on << 3) | flag_off; |
nxp_ip | 0:a624e2eeccac | 221 | regs[ IREF_GRP ] = iref; |
nxp_ip | 0:a624e2eeccac | 222 | |
nxp_ip | 0:a624e2eeccac | 223 | write( regs, sizeof( regs ) ); |
nxp_ip | 0:a624e2eeccac | 224 | |
nxp_ip | 0:a624e2eeccac | 225 | #if 0 |
nxp_ip | 0:a624e2eeccac | 226 | float n_of_steps; |
nxp_ip | 0:a624e2eeccac | 227 | float single_ramp_time; |
nxp_ip | 0:a624e2eeccac | 228 | float total_ramp_time; |
nxp_ip | 0:a624e2eeccac | 229 | |
nxp_ip | 0:a624e2eeccac | 230 | n_of_steps = (float)(((iref + 1) / iref_inc) * mult_factor); |
nxp_ip | 0:a624e2eeccac | 231 | single_ramp_time = n_of_steps * (prescaler ? 8.0 : 0.5); |
nxp_ip | 0:a624e2eeccac | 232 | total_ramp_time = single_ramp_time * ((ramp_flag == RAMP_UP_DOWN) ? 2.0 : 1.0); |
nxp_ip | 0:a624e2eeccac | 233 | 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 | 234 | 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 | 235 | #endif |
nxp_ip | 0:a624e2eeccac | 236 | |
nxp_ip | 0:a624e2eeccac | 237 | 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 | 238 | } |
nxp_ip | 0:a624e2eeccac | 239 | |
nxp_ip | 0:a624e2eeccac | 240 | |
nxp_ip | 0:a624e2eeccac | 241 | void PCA9955A::dump_gradation_registers( void ) |
nxp_ip | 0:a624e2eeccac | 242 | { |
nxp_ip | 0:a624e2eeccac | 243 | char data[ 23 ]; |
nxp_ip | 0:a624e2eeccac | 244 | |
nxp_ip | 0:a624e2eeccac | 245 | read( RAMP_RATE_GRP0, data, sizeof( data ) ); |
nxp_ip | 0:a624e2eeccac | 246 | |
nxp_ip | 0:a624e2eeccac | 247 | printf( "GRAD_MODE_SEL[1|0] = 0x%02X%02X\r\n", data[ 17 ], data[ 16 ] ); |
nxp_ip | 0:a624e2eeccac | 248 | 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 | 249 | printf( "GRAD_CNTL = 0x%02X\r\n", data[ 22 ] ); |
nxp_ip | 0:a624e2eeccac | 250 | 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 | 251 | 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 | 252 | 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 | 253 | printf( "IREF = 0x%02X 0x%02X 0x%02X 0x%02X\r\n", data[ 3 ], data[ 7 ], data[ 11 ], data[ 15 ] ); |
nxp_ip | 0:a624e2eeccac | 254 | printf( "\r\n" ); |
nxp_ip | 0:a624e2eeccac | 255 | } |