PCA9629A component library

Dependents:   PCA9629A_Hello

Committer:
nxp_ip
Date:
Fri Sep 12 08:10:19 2014 +0000
Revision:
0:0c797805233b
PCA9629 "A". The "A" version component library. Version 1.1.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nxp_ip 0:0c797805233b 1 /** A sample code for PCA9629A
nxp_ip 0:0c797805233b 2 *
nxp_ip 0:0c797805233b 3 * @author Akifumi (Tedd) OKANO, NXP Semiconductors
nxp_ip 0:0c797805233b 4 * @version 1.1
nxp_ip 0:0c797805233b 5 * @date 12-Sep-2012
nxp_ip 0:0c797805233b 6 *
nxp_ip 0:0c797805233b 7 * revision history (PCA9629A)
nxp_ip 0:0c797805233b 8 * version 0.1 (05-Jun-2013) : PCA9629"A" initial version
nxp_ip 0:0c797805233b 9 * version 0.2 (05-Jun-2013) : register name fix, register description added
nxp_ip 0:0c797805233b 10 * version 1.0 (23-Apr-2014) : unnecessary parameter for constructor has been removed
nxp_ip 0:0c797805233b 11 * version 1.1 (12-Sep-2014) : constructor variation added. ramp parameter API added
nxp_ip 0:0c797805233b 12 *
nxp_ip 0:0c797805233b 13 * Released under the Apache 2 license License
nxp_ip 0:0c797805233b 14 *
nxp_ip 0:0c797805233b 15 * An operation sample of PCU9629A stepper motor controller.
nxp_ip 0:0c797805233b 16 * The mbed accesses the PCU9629A registers through I2C.
nxp_ip 0:0c797805233b 17 *
nxp_ip 0:0c797805233b 18 * About PCA9629A:
nxp_ip 0:0c797805233b 19 * http://www.nxp.com/products/interface_and_connectivity/i2c/i2c_bus_controller_and_bridge_ics/PCA9629APW.html
nxp_ip 0:0c797805233b 20 */
nxp_ip 0:0c797805233b 21
nxp_ip 0:0c797805233b 22 #include "mbed.h"
nxp_ip 0:0c797805233b 23 #include "PCA9629A.h"
nxp_ip 0:0c797805233b 24
nxp_ip 0:0c797805233b 25 #define STEP_RESOLUTION 333333 // 1/(3e-6) = 333333
nxp_ip 0:0c797805233b 26
nxp_ip 0:0c797805233b 27 char *reg_name[] = {
nxp_ip 0:0c797805233b 28 "MODE", "WDTOI", "WDCNTL", "IO_CFG",
nxp_ip 0:0c797805233b 29 "INTMODE", "MSK", "INTSTAT", "IP", "INT_MTR_ACT", "EXTRASTEPS0", "EXTRASTEPS1",
nxp_ip 0:0c797805233b 30 "OP_CFG", "OP_STAT_PHS",
nxp_ip 0:0c797805233b 31 "RUCNTL", "RDCNTL",
nxp_ip 0:0c797805233b 32 "PMA", "LOOPDLY_CW", "LOOPDLY_CCW",
nxp_ip 0:0c797805233b 33 "CWSCOUNTL", "CWSCOUNTH", "CCWSCOUNTL", "CCWSCOUNTH",
nxp_ip 0:0c797805233b 34 "CWPWL", "CWPWH", "CCWPWL", "CCWPWH",
nxp_ip 0:0c797805233b 35 "MCNTL",
nxp_ip 0:0c797805233b 36 "SUBADR1", "SUBADR2", "SUBADR3", "ALLCALLADR",
nxp_ip 0:0c797805233b 37 "STEPCOUNT0", "STEPCOUNT1", "STEPCOUNT2", "STEPCOUNT3"
nxp_ip 0:0c797805233b 38 };
nxp_ip 0:0c797805233b 39
nxp_ip 0:0c797805233b 40 PCA9629A::PCA9629A(
nxp_ip 0:0c797805233b 41 PinName I2C_sda,
nxp_ip 0:0c797805233b 42 PinName I2C_scl,
nxp_ip 0:0c797805233b 43 char I2C_address
nxp_ip 0:0c797805233b 44 ) : i2c_p( new I2C( I2C_sda, I2C_scl ) ), i2c( *i2c_p ), i2c_addr( I2C_address )
nxp_ip 0:0c797805233b 45 {
nxp_ip 0:0c797805233b 46 i2c.frequency( I2C_SCL_FREQUENCY );
nxp_ip 0:0c797805233b 47 init_registers();
nxp_ip 0:0c797805233b 48 }
nxp_ip 0:0c797805233b 49
nxp_ip 0:0c797805233b 50 PCA9629A::PCA9629A(
nxp_ip 0:0c797805233b 51 I2C &i2c_,
nxp_ip 0:0c797805233b 52 char I2C_address
nxp_ip 0:0c797805233b 53 ) : i2c_p( NULL ), i2c( i2c_ ), i2c_addr( I2C_address )
nxp_ip 0:0c797805233b 54 {
nxp_ip 0:0c797805233b 55 init_registers();
nxp_ip 0:0c797805233b 56 }
nxp_ip 0:0c797805233b 57
nxp_ip 0:0c797805233b 58 PCA9629A::~PCA9629A()
nxp_ip 0:0c797805233b 59 {
nxp_ip 0:0c797805233b 60 if ( NULL != i2c_p )
nxp_ip 0:0c797805233b 61 delete i2c_p;
nxp_ip 0:0c797805233b 62 }
nxp_ip 0:0c797805233b 63
nxp_ip 0:0c797805233b 64 void PCA9629A::software_reset( void )
nxp_ip 0:0c797805233b 65 {
nxp_ip 0:0c797805233b 66 char v = 0x06;
nxp_ip 0:0c797805233b 67
nxp_ip 0:0c797805233b 68 i2c.write( 0x00, &v, 1 );
nxp_ip 0:0c797805233b 69 wait_ms( 1 );
nxp_ip 0:0c797805233b 70 }
nxp_ip 0:0c797805233b 71
nxp_ip 0:0c797805233b 72 void PCA9629A::init_registers( void )
nxp_ip 0:0c797805233b 73 {
nxp_ip 0:0c797805233b 74 char init_array[] = { 0x80, // register access start address (0x00) with incremental access flag (MSB)
nxp_ip 0:0c797805233b 75 0x20, 0x0A, 0x00, 0x03, 0x13, 0x1C, // for registers MODE - MSK (0x00 - 0x07
nxp_ip 0:0c797805233b 76 0x00, 0x00, 0x68, 0x00, 0x00, // for registers INTSTAT - EXTRASTEPS1 (0x06, 0xA)
nxp_ip 0:0c797805233b 77 0x10, 0x80, // for registers OP_CFG_PHS and OP_STAT_TO (0x0B - 0xC)
nxp_ip 0:0c797805233b 78 0x09, 0x09, 0x01, 0x7D, 0x7D, // for registers RUCNTL - LOOPDLY_CCW (0xD- 0x10)
nxp_ip 0:0c797805233b 79 0xFF, 0x01, 0xFF, 0x01, 0x05, 0x0D, 0x05, 0x0D, // for registers CWSCOUNTL - MCNTL (0x12 - 0x1A)
nxp_ip 0:0c797805233b 80 0x20, // for register MCNTL (0x1A)
nxp_ip 0:0c797805233b 81 0xE2, 0xE4, 0xE6, 0xE0 // for registers SUBADR1 - ALLCALLADR (0x1B - 0x1E)
nxp_ip 0:0c797805233b 82 };
nxp_ip 0:0c797805233b 83
nxp_ip 0:0c797805233b 84 set_all_registers( init_array, sizeof( init_array ) );
nxp_ip 0:0c797805233b 85 }
nxp_ip 0:0c797805233b 86
nxp_ip 0:0c797805233b 87 void PCA9629A::set_all_registers( char *a, char size )
nxp_ip 0:0c797805233b 88 {
nxp_ip 0:0c797805233b 89 int error_code;
nxp_ip 0:0c797805233b 90
nxp_ip 0:0c797805233b 91 error_code = i2c.write( i2c_addr, a, size );
nxp_ip 0:0c797805233b 92
nxp_ip 0:0c797805233b 93 if ( error_code )
nxp_ip 0:0c797805233b 94 error( "error @ initializing PCA9629A" );
nxp_ip 0:0c797805233b 95 }
nxp_ip 0:0c797805233b 96
nxp_ip 0:0c797805233b 97 void PCA9629A::write( RegisterName register_name, char value )
nxp_ip 0:0c797805233b 98 {
nxp_ip 0:0c797805233b 99 int error_code;
nxp_ip 0:0c797805233b 100 char cmd[ 2 ];
nxp_ip 0:0c797805233b 101
nxp_ip 0:0c797805233b 102 cmd[ 0 ] = register_name;
nxp_ip 0:0c797805233b 103 cmd[ 1 ] = value;
nxp_ip 0:0c797805233b 104
nxp_ip 0:0c797805233b 105 error_code = i2c.write( i2c_addr, cmd, 2 );
nxp_ip 0:0c797805233b 106
nxp_ip 0:0c797805233b 107 if ( error_code )
nxp_ip 0:0c797805233b 108 error( "PCA9629A writing failed\r\n" );
nxp_ip 0:0c797805233b 109 }
nxp_ip 0:0c797805233b 110
nxp_ip 0:0c797805233b 111 void PCA9629A::write( RegisterNameFor16bitAccess register_name, short value )
nxp_ip 0:0c797805233b 112 {
nxp_ip 0:0c797805233b 113 int error_code;
nxp_ip 0:0c797805233b 114 char cmd[ 3 ];
nxp_ip 0:0c797805233b 115
nxp_ip 0:0c797805233b 116 cmd[ 0 ] = register_name;
nxp_ip 0:0c797805233b 117 cmd[ 1 ] = value & 0xFF;
nxp_ip 0:0c797805233b 118 cmd[ 2 ] = value >> 8;
nxp_ip 0:0c797805233b 119
nxp_ip 0:0c797805233b 120 error_code = i2c.write( i2c_addr, cmd, 3 );
nxp_ip 0:0c797805233b 121
nxp_ip 0:0c797805233b 122 if ( error_code )
nxp_ip 0:0c797805233b 123 error( "PCA9629A writing failed\r\n" );
nxp_ip 0:0c797805233b 124 }
nxp_ip 0:0c797805233b 125
nxp_ip 0:0c797805233b 126 char PCA9629A::read( RegisterName register_name )
nxp_ip 0:0c797805233b 127 {
nxp_ip 0:0c797805233b 128 int error_code;
nxp_ip 0:0c797805233b 129 char cmd;
nxp_ip 0:0c797805233b 130 char data;
nxp_ip 0:0c797805233b 131
nxp_ip 0:0c797805233b 132 cmd = register_name;
nxp_ip 0:0c797805233b 133
nxp_ip 0:0c797805233b 134 error_code = i2c.write( i2c_addr, &cmd, 1, false );
nxp_ip 0:0c797805233b 135
nxp_ip 0:0c797805233b 136 if ( error_code )
nxp_ip 0:0c797805233b 137 error( "PCA9629A reading (command phase) failed\r\n" );
nxp_ip 0:0c797805233b 138
nxp_ip 0:0c797805233b 139 error_code = i2c.read( i2c_addr, &data, 1 );
nxp_ip 0:0c797805233b 140
nxp_ip 0:0c797805233b 141 if ( error_code )
nxp_ip 0:0c797805233b 142 error( "PCA9629A reading (data phase) failed\r\n" );
nxp_ip 0:0c797805233b 143
nxp_ip 0:0c797805233b 144 return ( data );
nxp_ip 0:0c797805233b 145 }
nxp_ip 0:0c797805233b 146
nxp_ip 0:0c797805233b 147 short PCA9629A::read( RegisterNameFor16bitAccess register_name )
nxp_ip 0:0c797805233b 148 {
nxp_ip 0:0c797805233b 149 int error_code;
nxp_ip 0:0c797805233b 150 char cmd;
nxp_ip 0:0c797805233b 151 char data[ 2 ];
nxp_ip 0:0c797805233b 152
nxp_ip 0:0c797805233b 153 cmd = register_name;
nxp_ip 0:0c797805233b 154
nxp_ip 0:0c797805233b 155 error_code = i2c.write( i2c_addr, &cmd, 1, false );
nxp_ip 0:0c797805233b 156
nxp_ip 0:0c797805233b 157 if ( error_code )
nxp_ip 0:0c797805233b 158 error( "PCA9629A reading (command phase) failed\r\n" );
nxp_ip 0:0c797805233b 159
nxp_ip 0:0c797805233b 160 error_code = i2c.read( i2c_addr, data, 2 );
nxp_ip 0:0c797805233b 161
nxp_ip 0:0c797805233b 162 if ( error_code )
nxp_ip 0:0c797805233b 163 error( "PCA9629A reading (data phase) failed\r\n" );
nxp_ip 0:0c797805233b 164
nxp_ip 0:0c797805233b 165 return ( data[ 1 ] << 8 | data[ 0 ] );
nxp_ip 0:0c797805233b 166 }
nxp_ip 0:0c797805233b 167
nxp_ip 0:0c797805233b 168 long PCA9629A::read( RegisterNameFor32bitAccess register_name )
nxp_ip 0:0c797805233b 169 {
nxp_ip 0:0c797805233b 170 int error_code;
nxp_ip 0:0c797805233b 171 char cmd;
nxp_ip 0:0c797805233b 172 char data[ 4 ];
nxp_ip 0:0c797805233b 173
nxp_ip 0:0c797805233b 174 cmd = register_name | 0x80;
nxp_ip 0:0c797805233b 175
nxp_ip 0:0c797805233b 176 error_code = i2c.write( i2c_addr, &cmd, 1, false );
nxp_ip 0:0c797805233b 177
nxp_ip 0:0c797805233b 178 if ( error_code )
nxp_ip 0:0c797805233b 179 error( "PCA9629A reading (command phase) failed\r\n" );
nxp_ip 0:0c797805233b 180
nxp_ip 0:0c797805233b 181 error_code = i2c.read( i2c_addr, data, 4 );
nxp_ip 0:0c797805233b 182
nxp_ip 0:0c797805233b 183 if ( error_code )
nxp_ip 0:0c797805233b 184 error( "PCA9629A reading (data phase) failed\r\n" );
nxp_ip 0:0c797805233b 185
nxp_ip 0:0c797805233b 186 printf( "0x %02X %02X %02X %02X\r\n", data[3], data[2], data[1], data[0] );
nxp_ip 0:0c797805233b 187
nxp_ip 0:0c797805233b 188 return ( data[ 3 ] << 24 | data[ 2 ] << 16 | data[ 1 ] << 8 | data[ 0 ] );
nxp_ip 0:0c797805233b 189 }
nxp_ip 0:0c797805233b 190
nxp_ip 0:0c797805233b 191 void PCA9629A::start( Direction dir )
nxp_ip 0:0c797805233b 192 {
nxp_ip 0:0c797805233b 193 write( MCNTL, 0xC0 | dir );
nxp_ip 0:0c797805233b 194 }
nxp_ip 0:0c797805233b 195
nxp_ip 0:0c797805233b 196 void PCA9629A::stop( void )
nxp_ip 0:0c797805233b 197 {
nxp_ip 0:0c797805233b 198 write( MCNTL, 0xA0 );
nxp_ip 0:0c797805233b 199 }
nxp_ip 0:0c797805233b 200
nxp_ip 0:0c797805233b 201
nxp_ip 0:0c797805233b 202 short PCA9629A::pps( Direction dir, PrescalerRange prescaler, int pps )
nxp_ip 0:0c797805233b 203 {
nxp_ip 0:0c797805233b 204 int step_pulse_width;
nxp_ip 0:0c797805233b 205
nxp_ip 0:0c797805233b 206 step_pulse_width = STEP_RESOLUTION / ((1 << prescaler) * pps);
nxp_ip 0:0c797805233b 207
nxp_ip 0:0c797805233b 208 if ( step_pulse_width & 0xE000 ) { //error( "pps setting: out of range" );
nxp_ip 0:0c797805233b 209 step_pulse_width = 0x1FFF;
nxp_ip 0:0c797805233b 210 printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / ((float)0x1FFF * (float)(1 << prescaler)) );
nxp_ip 0:0c797805233b 211 }
nxp_ip 0:0c797805233b 212 if ( !step_pulse_width ) { //error( "pps setting: out of range" );
nxp_ip 0:0c797805233b 213 step_pulse_width = 0x1;
nxp_ip 0:0c797805233b 214 printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / (float)(1 << prescaler) );
nxp_ip 0:0c797805233b 215 }
nxp_ip 0:0c797805233b 216
nxp_ip 0:0c797805233b 217 step_pulse_width |= (prescaler << 13);
nxp_ip 0:0c797805233b 218
nxp_ip 0:0c797805233b 219 write( (dir == CW) ? CW__STEP_WIDTH : CCW_STEP_WIDTH, step_pulse_width );
nxp_ip 0:0c797805233b 220
nxp_ip 0:0c797805233b 221 return ( step_pulse_width );
nxp_ip 0:0c797805233b 222 }
nxp_ip 0:0c797805233b 223
nxp_ip 0:0c797805233b 224 short PCA9629A::pps( Direction dir, float pulse_per_second )
nxp_ip 0:0c797805233b 225 {
nxp_ip 0:0c797805233b 226 char p = 0;
nxp_ip 0:0c797805233b 227 char ratio;
nxp_ip 0:0c797805233b 228
nxp_ip 0:0c797805233b 229 ratio = (char)(40.6901 / pulse_per_second);
nxp_ip 0:0c797805233b 230
nxp_ip 0:0c797805233b 231 p = (ratio & 0x01) ? 1 : p;
nxp_ip 0:0c797805233b 232 p = (ratio & 0x02) ? 2 : p;
nxp_ip 0:0c797805233b 233 p = (ratio & 0x04) ? 3 : p;
nxp_ip 0:0c797805233b 234 p = (ratio & 0x08) ? 4 : p;
nxp_ip 0:0c797805233b 235 p = (ratio & 0x10) ? 5 : p;
nxp_ip 0:0c797805233b 236 p = (ratio & 0x20) ? 6 : p;
nxp_ip 0:0c797805233b 237 p = (ratio & 0x40) ? 7 : p;
nxp_ip 0:0c797805233b 238
nxp_ip 0:0c797805233b 239 return ( pps( dir, (PrescalerRange)p, (int)pulse_per_second ) );
nxp_ip 0:0c797805233b 240 }
nxp_ip 0:0c797805233b 241
nxp_ip 0:0c797805233b 242 void PCA9629A::steps( Direction dir, int step_count )
nxp_ip 0:0c797805233b 243 {
nxp_ip 0:0c797805233b 244 write( (dir == CW) ? CW__STEP_COUNT : CCW_STEP_COUNT, step_count );
nxp_ip 0:0c797805233b 245 }
nxp_ip 0:0c797805233b 246
nxp_ip 0:0c797805233b 247 void PCA9629A::ramp_up( char rate )
nxp_ip 0:0c797805233b 248 {
nxp_ip 0:0c797805233b 249 write( RUCNTL, rate ? (0x30 | (rate -1)) : 0x00 );
nxp_ip 0:0c797805233b 250 }
nxp_ip 0:0c797805233b 251
nxp_ip 0:0c797805233b 252 void PCA9629A::ramp_down( char rate )
nxp_ip 0:0c797805233b 253 {
nxp_ip 0:0c797805233b 254 write( RDCNTL, rate ? (0x30 | (rate -1)) : 0x00 );
nxp_ip 0:0c797805233b 255 }
nxp_ip 0:0c797805233b 256
nxp_ip 0:0c797805233b 257 void PCA9629A::register_dump( void )
nxp_ip 0:0c797805233b 258 {
nxp_ip 0:0c797805233b 259 char data[ 0x23 ];
nxp_ip 0:0c797805233b 260 char cmd = 0x80;
nxp_ip 0:0c797805233b 261 int i;
nxp_ip 0:0c797805233b 262 int j;
nxp_ip 0:0c797805233b 263
nxp_ip 0:0c797805233b 264 i2c.write( i2c_addr, &cmd, 1 );
nxp_ip 0:0c797805233b 265 i2c.read( i2c_addr, data, sizeof( data ) );
nxp_ip 0:0c797805233b 266
nxp_ip 0:0c797805233b 267 printf( "PCA9629A register dump\r\n" );
nxp_ip 0:0c797805233b 268
nxp_ip 0:0c797805233b 269 for ( i = 0, j = 0x14; i <= 0x12; i++, j++ )
nxp_ip 0:0c797805233b 270 printf( " %-13s (0x%02X): 0x%02X %-13s (0x%02X): 0x%02X\r\n", reg_name[ i ], i, data[ i ], reg_name[ j ], j, data[ j ] );
nxp_ip 0:0c797805233b 271
nxp_ip 0:0c797805233b 272 printf( " %-13s (0x%02X): 0x%02X\r\n", reg_name[ 0x13 ], 0x13, data[ 0x13 ] );
nxp_ip 0:0c797805233b 273 }
nxp_ip 0:0c797805233b 274
nxp_ip 0:0c797805233b 275
nxp_ip 0:0c797805233b 276 void PCA9629A::speed_change( unsigned short pw )
nxp_ip 0:0c797805233b 277 {
nxp_ip 0:0c797805233b 278 #ifdef MBED_PCA9629
nxp_ip 0:0c797805233b 279 // this is for PCA9629(non-A version)
nxp_ip 0:0c797805233b 280 char cmd0[] = { PCA9629A::MCNTL, 0x00}; // data for stop the motor
nxp_ip 0:0c797805233b 281 char cmd1[] = { PCA9629A::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; // data for rewrite pulse width
nxp_ip 0:0c797805233b 282 char cmd2[] = { PCA9629A::MCNTL, 0xB4}; // start // data for start again
nxp_ip 0:0c797805233b 283 wait_us(10);
nxp_ip 0:0c797805233b 284
nxp_ip 0:0c797805233b 285 i2c.write( i2c_addr, cmd0, sizeof( cmd0 ), true ); // stop the motor
nxp_ip 0:0c797805233b 286 wait_us(50);
nxp_ip 0:0c797805233b 287 i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true ); // rewrite pulse width
nxp_ip 0:0c797805233b 288 i2c.write( i2c_addr, cmd2, sizeof( cmd2 ), false ); // start again
nxp_ip 0:0c797805233b 289 #else
nxp_ip 0:0c797805233b 290 char cmd1[] = { PCA9629A::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; // data for rewrite pulse width
nxp_ip 0:0c797805233b 291
nxp_ip 0:0c797805233b 292 i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true ); // rewrite pulse width
nxp_ip 0:0c797805233b 293 #endif
nxp_ip 0:0c797805233b 294 }