removed unnecessary message by printf (in 32bit register read function)
Fork of PCA9629A by
PCA9629A.cpp
- Committer:
- nxp_ip
- Date:
- 2014-09-12
- Revision:
- 0:0c797805233b
- Child:
- 1:b03b599af5ee
File content as of revision 0:0c797805233b:
/** A sample code for PCA9629A * * @author Akifumi (Tedd) OKANO, NXP Semiconductors * @version 1.1 * @date 12-Sep-2012 * * revision history (PCA9629A) * version 0.1 (05-Jun-2013) : PCA9629"A" initial version * version 0.2 (05-Jun-2013) : register name fix, register description added * version 1.0 (23-Apr-2014) : unnecessary parameter for constructor has been removed * version 1.1 (12-Sep-2014) : constructor variation added. ramp parameter API added * * Released under the Apache 2 license License * * An operation sample of PCU9629A stepper motor controller. * The mbed accesses the PCU9629A registers through I2C. * * About PCA9629A: * http://www.nxp.com/products/interface_and_connectivity/i2c/i2c_bus_controller_and_bridge_ics/PCA9629APW.html */ #include "mbed.h" #include "PCA9629A.h" #define STEP_RESOLUTION 333333 // 1/(3e-6) = 333333 char *reg_name[] = { "MODE", "WDTOI", "WDCNTL", "IO_CFG", "INTMODE", "MSK", "INTSTAT", "IP", "INT_MTR_ACT", "EXTRASTEPS0", "EXTRASTEPS1", "OP_CFG", "OP_STAT_PHS", "RUCNTL", "RDCNTL", "PMA", "LOOPDLY_CW", "LOOPDLY_CCW", "CWSCOUNTL", "CWSCOUNTH", "CCWSCOUNTL", "CCWSCOUNTH", "CWPWL", "CWPWH", "CCWPWL", "CCWPWH", "MCNTL", "SUBADR1", "SUBADR2", "SUBADR3", "ALLCALLADR", "STEPCOUNT0", "STEPCOUNT1", "STEPCOUNT2", "STEPCOUNT3" }; PCA9629A::PCA9629A( PinName I2C_sda, PinName I2C_scl, char I2C_address ) : i2c_p( new I2C( I2C_sda, I2C_scl ) ), i2c( *i2c_p ), i2c_addr( I2C_address ) { i2c.frequency( I2C_SCL_FREQUENCY ); init_registers(); } PCA9629A::PCA9629A( I2C &i2c_, char I2C_address ) : i2c_p( NULL ), i2c( i2c_ ), i2c_addr( I2C_address ) { init_registers(); } PCA9629A::~PCA9629A() { if ( NULL != i2c_p ) delete i2c_p; } void PCA9629A::software_reset( void ) { char v = 0x06; i2c.write( 0x00, &v, 1 ); wait_ms( 1 ); } void PCA9629A::init_registers( void ) { char init_array[] = { 0x80, // register access start address (0x00) with incremental access flag (MSB) 0x20, 0x0A, 0x00, 0x03, 0x13, 0x1C, // for registers MODE - MSK (0x00 - 0x07 0x00, 0x00, 0x68, 0x00, 0x00, // for registers INTSTAT - EXTRASTEPS1 (0x06, 0xA) 0x10, 0x80, // for registers OP_CFG_PHS and OP_STAT_TO (0x0B - 0xC) 0x09, 0x09, 0x01, 0x7D, 0x7D, // for registers RUCNTL - LOOPDLY_CCW (0xD- 0x10) 0xFF, 0x01, 0xFF, 0x01, 0x05, 0x0D, 0x05, 0x0D, // for registers CWSCOUNTL - MCNTL (0x12 - 0x1A) 0x20, // for register MCNTL (0x1A) 0xE2, 0xE4, 0xE6, 0xE0 // for registers SUBADR1 - ALLCALLADR (0x1B - 0x1E) }; set_all_registers( init_array, sizeof( init_array ) ); } void PCA9629A::set_all_registers( char *a, char size ) { int error_code; error_code = i2c.write( i2c_addr, a, size ); if ( error_code ) error( "error @ initializing PCA9629A" ); } void PCA9629A::write( RegisterName register_name, char value ) { int error_code; char cmd[ 2 ]; cmd[ 0 ] = register_name; cmd[ 1 ] = value; error_code = i2c.write( i2c_addr, cmd, 2 ); if ( error_code ) error( "PCA9629A writing failed\r\n" ); } void PCA9629A::write( RegisterNameFor16bitAccess register_name, short value ) { int error_code; char cmd[ 3 ]; cmd[ 0 ] = register_name; cmd[ 1 ] = value & 0xFF; cmd[ 2 ] = value >> 8; error_code = i2c.write( i2c_addr, cmd, 3 ); if ( error_code ) error( "PCA9629A writing failed\r\n" ); } char PCA9629A::read( RegisterName register_name ) { int error_code; char cmd; char data; cmd = register_name; error_code = i2c.write( i2c_addr, &cmd, 1, false ); if ( error_code ) error( "PCA9629A reading (command phase) failed\r\n" ); error_code = i2c.read( i2c_addr, &data, 1 ); if ( error_code ) error( "PCA9629A reading (data phase) failed\r\n" ); return ( data ); } short PCA9629A::read( RegisterNameFor16bitAccess register_name ) { int error_code; char cmd; char data[ 2 ]; cmd = register_name; error_code = i2c.write( i2c_addr, &cmd, 1, false ); if ( error_code ) error( "PCA9629A reading (command phase) failed\r\n" ); error_code = i2c.read( i2c_addr, data, 2 ); if ( error_code ) error( "PCA9629A reading (data phase) failed\r\n" ); return ( data[ 1 ] << 8 | data[ 0 ] ); } long PCA9629A::read( RegisterNameFor32bitAccess register_name ) { int error_code; char cmd; char data[ 4 ]; cmd = register_name | 0x80; error_code = i2c.write( i2c_addr, &cmd, 1, false ); if ( error_code ) error( "PCA9629A reading (command phase) failed\r\n" ); error_code = i2c.read( i2c_addr, data, 4 ); if ( error_code ) error( "PCA9629A reading (data phase) failed\r\n" ); printf( "0x %02X %02X %02X %02X\r\n", data[3], data[2], data[1], data[0] ); return ( data[ 3 ] << 24 | data[ 2 ] << 16 | data[ 1 ] << 8 | data[ 0 ] ); } void PCA9629A::start( Direction dir ) { write( MCNTL, 0xC0 | dir ); } void PCA9629A::stop( void ) { write( MCNTL, 0xA0 ); } short PCA9629A::pps( Direction dir, PrescalerRange prescaler, int pps ) { int step_pulse_width; step_pulse_width = STEP_RESOLUTION / ((1 << prescaler) * pps); if ( step_pulse_width & 0xE000 ) { //error( "pps setting: out of range" ); step_pulse_width = 0x1FFF; printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / ((float)0x1FFF * (float)(1 << prescaler)) ); } if ( !step_pulse_width ) { //error( "pps setting: out of range" ); step_pulse_width = 0x1; printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / (float)(1 << prescaler) ); } step_pulse_width |= (prescaler << 13); write( (dir == CW) ? CW__STEP_WIDTH : CCW_STEP_WIDTH, step_pulse_width ); return ( step_pulse_width ); } short PCA9629A::pps( Direction dir, float pulse_per_second ) { char p = 0; char ratio; ratio = (char)(40.6901 / pulse_per_second); p = (ratio & 0x01) ? 1 : p; p = (ratio & 0x02) ? 2 : p; p = (ratio & 0x04) ? 3 : p; p = (ratio & 0x08) ? 4 : p; p = (ratio & 0x10) ? 5 : p; p = (ratio & 0x20) ? 6 : p; p = (ratio & 0x40) ? 7 : p; return ( pps( dir, (PrescalerRange)p, (int)pulse_per_second ) ); } void PCA9629A::steps( Direction dir, int step_count ) { write( (dir == CW) ? CW__STEP_COUNT : CCW_STEP_COUNT, step_count ); } void PCA9629A::ramp_up( char rate ) { write( RUCNTL, rate ? (0x30 | (rate -1)) : 0x00 ); } void PCA9629A::ramp_down( char rate ) { write( RDCNTL, rate ? (0x30 | (rate -1)) : 0x00 ); } void PCA9629A::register_dump( void ) { char data[ 0x23 ]; char cmd = 0x80; int i; int j; i2c.write( i2c_addr, &cmd, 1 ); i2c.read( i2c_addr, data, sizeof( data ) ); printf( "PCA9629A register dump\r\n" ); for ( i = 0, j = 0x14; i <= 0x12; i++, j++ ) 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 ] ); printf( " %-13s (0x%02X): 0x%02X\r\n", reg_name[ 0x13 ], 0x13, data[ 0x13 ] ); } void PCA9629A::speed_change( unsigned short pw ) { #ifdef MBED_PCA9629 // this is for PCA9629(non-A version) char cmd0[] = { PCA9629A::MCNTL, 0x00}; // data for stop the motor char cmd1[] = { PCA9629A::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; // data for rewrite pulse width char cmd2[] = { PCA9629A::MCNTL, 0xB4}; // start // data for start again wait_us(10); i2c.write( i2c_addr, cmd0, sizeof( cmd0 ), true ); // stop the motor wait_us(50); i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true ); // rewrite pulse width i2c.write( i2c_addr, cmd2, sizeof( cmd2 ), false ); // start again #else char cmd1[] = { PCA9629A::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; // data for rewrite pulse width i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true ); // rewrite pulse width #endif }