demo sample to drive PCU9955 and PCA9629
Dependencies: mbed I2C_slaves PCU9669 parallel_bus
Fork of mini_board_PCU9669 by
What is this?
This is a sample code to operate PCU9955 (16ch constant-current LED controller) and PCA9629 (intelligent stepper motor controller) through PCU9669 (3 channels (UltraFast mode * 2ch, FastModePlus *1ch) I2C bus controller).
This demo is written based on mini_board_PCU9669 sample code library and its API.
http://mbed.org/users/nxp_ip/code/mini_board_PCU9669/
Demo will shows how the LED controllers and stepper motor controllers works.
It uses a mini_board_PCU9669 board with mbed, 8 of PCU9955s and 5 PCA9629s.
Demo setup
(left-top: PCU9955 boards, left-bottom: mini-board PCU9669 with mbed, right: PCA9629 x5 board)
Board connections and device addresses
Reference:
User manual of PCU9669 demo board: Mini board PCU9669
http://www.nxp.com/documents/user_manual/UM10580.pdf
sample code : mbed programs
Import programmini_board_PCU9669
mini board PCU9669 (and PCA9665) sample code
Import programPCA9955_Hello
PCA9955 16 channel current drive(sink) LED driver sample code
Import programPCA9955_simple
very simple sample code for PCA9955 (16 channel current control LED driver)
Import programPCA9629_Hello
Sample code for PCA9629 operation
device infomation
PCU9669 (Parallel bus to 1 channel Fm+ and 2 channel UFm I2C-bus controller)
PCU9955 (16-channel UFm I²C-bus 57 mA constant current LED driver)
PCA9955 (16-channel Fm+ I²C-bus 57 mA constant current LED driver)
PCU9629 (Fm+ I2C-bus stepper motor controller)
Diff: demo_patterns.cpp
- Revision:
- 20:a266fa588bd8
- Child:
- 21:3b75b545ecfb
diff -r c91c6ab35677 -r a266fa588bd8 demo_patterns.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo_patterns.cpp Fri Oct 26 05:59:55 2012 +0000 @@ -0,0 +1,716 @@ +#include "demo_patterns.h" +#include "transfer_manager.h" +#include "PCx9955_reg.h" +#include "PCA9629_reg.h" +#include "PCU9669_access.h" // PCU9669 chip access interface + +#include "mbed.h" + +typedef struct pattern_st { + int duration; + void (*pattern_func)( int count ); +} +pattern; + +char gLEDs[ N_OF_LEDS ] = { 0 }; +int gCount = 0; + +char nine_step_intensity[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; +char sixteen_step_intensity[] = { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00 }; + +char gMot_cntl_order[ 5 ] = { MOT_ADDR5, MOT_ADDR6, MOT_ADDR7, MOT_ADDR8, MOT_ADDR9 }; +char gMot_cntl_order_halfturn[ 10 ] = { MOT_ADDR5, 0, MOT_ADDR6, MOT_ADDR7, MOT_ADDR8, MOT_ADDR9, 0, MOT_ADDR8, MOT_ADDR7, MOT_ADDR6 }; +char gMotor_count; + +typedef enum { + RED, + GREEN, + BLUE, +} +color; + +char rgb_mask[ 3 ][ 15 ] = { + { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 }, + { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0 } +}; + +char led_init_array[] = { + 0x80, // Command + 0x00, 0x05, // MODE1, MODE2 + 0xAA, 0xAA, 0xAA, 0xAA, // LEDOUT[3:0] + 0x80, 0x00, // GRPPWM, GRPFREQ + PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, // PWM[7:0] + PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, PWM_INIT, // PWM[15:8] + IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, // IREF[7:0] + IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, IREF_INIT, // IREF[15:8] + 0x08 // OFFSET: 1uS offsets +}; + +char led_norm_op_array[] = { + 0x80 | PWM0, // Command + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PWM[7:0] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PWM[14:8] +}; + +char mot_init_array[] = { + 0x80, + 0x20, 0xE2, 0xE4, 0xE6, 0xE0, 0x02, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 + 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) + 0x0F, 0x03, 0x0C, 0x0F, 0x03, 0x01, 0x01, 0x00, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) + 0x00, 0x00, 0x30, 0x00, 0x82, 0x06, 0x82, 0x06, // for registers SETMODE - CCWPWH (0x12 - 0x19) + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) + 0x00, 0x00, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) + 0x00, 0x00, 0x84 // for registers RMPCNTL - MCNTL (0x24 - 0x26) +}; + +char mot_all_stop[] = { + 0x26, 0x00 +}; + +char mot_all_start[] = { + 0x26, 0xBA +}; + +char mot_ramp_array[] = { + 0x80, + 0x20, 0xE2, 0xE4, 0xE6, 0xE0, 0xFF, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 + 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) + 0x0F, 0x03, 0x0C, 0x0F, 0x03, 0x00, 0x03, 0x03, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) + 0x00, 0x00, 0x30, 0x00, 0x97, 0x04, 0x97, 0x04, // for registers SETMODE - CCWPWH (0x12 - 0x19) + 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) + 0x0C, 0x0C, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) + 0x37, 0x00, 0x88 // for registers RMPCNTL - MCNTL (0x24 - 0x26) +}; + +char mot_vib_array[] = { + 0x80, + 0x20, 0xE2, 0xE4, 0xE6, 0xE0, 0xFF, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 + 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) + 0x0F, 0x03, 0x0C, 0x0F, 0x03, 0x00, 0x03, 0x03, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) + 0x00, 0x00, 0x30, 0x00, 0x82, 0x06, 0x82, 0x06, // for registers SETMODE - CCWPWH (0x12 - 0x19) + 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) + 0x0C, 0x0C, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) + 0x00, 0x00, 0xBA // for registers RMPCNTL - MCNTL (0x24 - 0x26) +}; + +//#define INTERVAL128MS +#ifdef INTERVAL128MS +char mot_norm_op_array[] = { + 0x80, + 0x20, 0xE2, 0xE4, 0xE6, 0xE0, 0x02, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 + 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) + 0x0F, 0x03, 0x0C, 0x0F, 0x03, 0x00, 0x01, 0x00, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) + 0x00, 0x00, 0x30, 0x00, 0xF2, 0x06, 0xF2, 0x06, // for registers SETMODE - CCWPWH (0x12 - 0x19) + 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) + 0x00, 0x00, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) + 0x00, 0x00, 0x00 // for registers RMPCNTL - MCNTL (0x24 - 0x26) +}; + +char mot_half_array[] = { + 0x80, + 0x20, 0xE2, 0xE4, 0xE6, 0xE0, 0x02, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 + 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) + 0x0F, 0x03, 0x0C, 0x0F, 0x03, 0x00, 0x01, 0x00, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) + 0x00, 0x00, 0x30, 0x00, 0xF2, 0x06, 0xF2, 0x06, // for registers SETMODE - CCWPWH (0x12 - 0x19) + 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) + 0x00, 0x00, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) + 0x00, 0x00, 0x00 // for registers RMPCNTL - MCNTL (0x24 - 0x26) +}; +#else +char mot_norm_op_array[] = { + 0x80, + 0x20, 0xE2, 0xE4, 0xE6, 0xE0, 0x02, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 + 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) + 0x0F, 0x03, 0x0C, 0x0F, 0x03, 0x00, 0x01, 0x00, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) + 0x00, 0x00, 0x30, 0x00, 0xE4, 0x0D, 0xE4, 0x0D, // for registers SETMODE - CCWPWH (0x12 - 0x19) + 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) + 0x00, 0x00, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) + 0x00, 0x00, 0x00 // for registers RMPCNTL - MCNTL (0x24 - 0x26) +}; + +char mot_half_array[] = { + 0x80, + 0x20, 0xE2, 0xE4, 0xE6, 0xE0, 0x02, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 + 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) + 0x0F, 0x03, 0x0C, 0x0F, 0x03, 0x00, 0x01, 0x00, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) + 0x00, 0x00, 0x30, 0x00, 0xE4, 0x0D, 0xE4, 0x0D, // for registers SETMODE - CCWPWH (0x12 - 0x19) + 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) + 0x00, 0x00, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) + 0x00, 0x00, 0x00 // for registers RMPCNTL - MCNTL (0x24 - 0x26) +}; +#endif + + +transaction led_init_transfer[] = { + { PCx9955_ADDR0, led_init_array, sizeof( led_init_array ) }, + { PCx9955_ADDR1, led_init_array, sizeof( led_init_array ) }, + { PCx9955_ADDR2, led_init_array, sizeof( led_init_array ) }, + { PCx9955_ADDR3, led_init_array, sizeof( led_init_array ) }, +}; + +transaction led_norm_op_transfer[] = { + { PCx9955_ADDR0, led_norm_op_array, sizeof( led_norm_op_array ) }, + { PCx9955_ADDR1, led_norm_op_array, sizeof( led_norm_op_array ) }, + { PCx9955_ADDR2, led_norm_op_array, sizeof( led_norm_op_array ) }, + { PCx9955_ADDR3, led_norm_op_array, sizeof( led_norm_op_array ) }, +}; + +transaction mot_init_transfer[] = { + { MOT_ADDR5, mot_init_array, sizeof( mot_init_array ) }, + { MOT_ADDR6, mot_init_array, sizeof( mot_init_array ) }, + { MOT_ADDR7, mot_init_array, sizeof( mot_init_array ) }, + { MOT_ADDR8, mot_init_array, sizeof( mot_init_array ) }, + { MOT_ADDR9, mot_init_array, sizeof( mot_init_array ) }, +}; + +transaction mot_norm_op_transfer[] = { + { MOT_ADDR5, mot_norm_op_array, sizeof( mot_norm_op_array ) }, + { MOT_ADDR6, mot_norm_op_array, sizeof( mot_norm_op_array ) }, + { MOT_ADDR7, mot_norm_op_array, sizeof( mot_norm_op_array ) }, + { MOT_ADDR8, mot_norm_op_array, sizeof( mot_norm_op_array ) }, + { MOT_ADDR9, mot_norm_op_array, sizeof( mot_norm_op_array ) }, +}; + +transaction mot_half_transfer[] = { + { MOT_ADDR5, mot_norm_op_array, sizeof( mot_norm_op_array ) }, + { MOT_ADDR6, mot_half_array, sizeof( mot_half_array ) }, + { MOT_ADDR7, mot_half_array, sizeof( mot_half_array ) }, + { MOT_ADDR8, mot_half_array, sizeof( mot_half_array ) }, + { MOT_ADDR9, mot_norm_op_array, sizeof( mot_norm_op_array ) }, +}; + +transaction mot_half_setup_transfer[] = { + { MOT_ADDR5, mot_half_array, sizeof( mot_half_array ) }, + { MOT_ADDR6, mot_half_array, sizeof( mot_half_array ) }, + { MOT_ADDR7, mot_half_array, sizeof( mot_half_array ) }, + { MOT_ADDR8, mot_half_array, sizeof( mot_half_array ) }, + { MOT_ADDR9, mot_half_array, sizeof( mot_half_array ) }, +}; + +transaction mot_all_stop_transfer[] = { + { MOT_ADDR5, mot_all_stop, sizeof( mot_all_stop ) }, + { MOT_ADDR6, mot_all_stop, sizeof( mot_all_stop ) }, + { MOT_ADDR7, mot_all_stop, sizeof( mot_all_stop ) }, + { MOT_ADDR8, mot_all_stop, sizeof( mot_all_stop ) }, + { MOT_ADDR9, mot_all_stop, sizeof( mot_all_stop ) }, +}; + +transaction mot_all_start_transfer[] = { + { MOT_ADDR5, mot_all_start, sizeof( mot_all_start ) }, + { MOT_ADDR6, mot_all_start, sizeof( mot_all_start ) }, + { MOT_ADDR7, mot_all_start, sizeof( mot_all_start ) }, + { MOT_ADDR8, mot_all_start, sizeof( mot_all_start ) }, + { MOT_ADDR9, mot_all_start, sizeof( mot_all_start ) }, +}; + +transaction mot_all_vib_transfer[] = { + { MOT_ADDR5, mot_vib_array, sizeof( mot_vib_array ) }, + { MOT_ADDR6, mot_vib_array, sizeof( mot_vib_array ) }, + { MOT_ADDR7, mot_vib_array, sizeof( mot_vib_array ) }, + { MOT_ADDR8, mot_vib_array, sizeof( mot_vib_array ) }, + { MOT_ADDR9, mot_vib_array, sizeof( mot_vib_array ) }, +}; + +transaction mot_all_ramp_transfer[] = { + { MOT_ADDR5, mot_ramp_array, sizeof( mot_ramp_array ) }, + { MOT_ADDR6, mot_ramp_array, sizeof( mot_ramp_array ) }, + { MOT_ADDR7, mot_ramp_array, sizeof( mot_ramp_array ) }, + { MOT_ADDR8, mot_ramp_array, sizeof( mot_ramp_array ) }, + { MOT_ADDR9, mot_ramp_array, sizeof( mot_ramp_array ) }, +}; + +void init_slave_devices( void ) { + // init all slave's registers + setup_transfer( CH_FM_PLUS, mot_init_transfer, sizeof( mot_init_transfer ) / sizeof( transaction ) ); + setup_transfer( CH_UFM1, led_init_transfer, sizeof( led_init_transfer ) / sizeof( transaction ) ); + setup_transfer( CH_UFM2, led_init_transfer, sizeof( led_init_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); // motors are aligned using interrupt input of PCA9629 + start( CH_UFM1 ); + start( CH_UFM2 ); + + wait_sec( 0.5 ); + + // update motor control buffer configuration + + setup_transfer( CH_FM_PLUS, mot_norm_op_transfer, sizeof( mot_norm_op_transfer ) / sizeof( transaction ) ); + setup_transfer( CH_UFM1, led_norm_op_transfer, sizeof( led_norm_op_transfer ) / sizeof( transaction ) ); + setup_transfer( CH_UFM2, led_norm_op_transfer, sizeof( led_norm_op_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); // just update PCA9629 registers. no motor action + start( CH_UFM1 ); + start( CH_UFM2 ); +} + +void single_byte_write_into_a_PCA9629( char ch, char i2c_addr, char reg_addr, char val ) { + transaction t; + char data[ 2 ]; + + data[ 0 ] = reg_addr; + data[ 1 ] = val; + + t.i2c_address = i2c_addr; + t.data = data; + t.length = 2; + + setup_transfer( ch, &t, 1 ); + start( CH_FM_PLUS ); +} + +void ramp_all_PCA9629( void ) { + setup_transfer( CH_FM_PLUS, mot_all_ramp_transfer, sizeof( mot_all_ramp_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); +} +void vib_all_PCA9629( void ) { + setup_transfer( CH_FM_PLUS, mot_all_vib_transfer, sizeof( mot_all_vib_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); +} +void start_all_PCA9629( void ) { + setup_transfer( CH_FM_PLUS, mot_all_start_transfer, sizeof( mot_all_start_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); +} +void stop_all_PCA9629( void ) { + setup_transfer( CH_FM_PLUS, mot_all_stop_transfer, sizeof( mot_all_stop_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); +} +void align_all_PCA9629( void ) { + setup_transfer( CH_FM_PLUS, mot_init_transfer, sizeof( mot_init_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); +} + +void all_LEDs_value( char v ) { + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = v; +} + +void all_LEDs_turn_off() { + all_LEDs_value( 0x00 ); +} + +void all_LEDs_turn_on() { + all_LEDs_value( 0xFF ); +} + +void pattern_rampup( int count ) { + if ( count == 0 ) { + all_LEDs_turn_off(); + return; + } + + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = count & 0xFF; +} + +void pattern_rampup_and_down( int count ) { + if ( !(count & 0xFF) ) { + ramp_all_PCA9629(); + all_LEDs_turn_off(); + return; + } + + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = (((count & 0x80) ? ~count : count) << 1) & 0xFF; +} + +void pattern_rampup_and_down_w_color( int count ) { + static int color; + + color = (!count || (3 <= color)) ? 0 : color; + + if ( !(count & 0xFF) ) { + ramp_all_PCA9629(); + all_LEDs_turn_off(); + color++; + return; + } + + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = (rgb_mask[ color ][ i % N_LED_PER_BOARD ]) ? (((count & 0x80) ? ~count : count) << 1) & 0xFF : 0x00; +} + + +void pattern_colors2( int count ) { + + if ( !count ) { + gMotor_count = 0; + setup_transfer( CH_FM_PLUS, mot_norm_op_transfer, sizeof( mot_norm_op_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); // just update PCA9629 registers. no motor action + } + + if ( !((count + 20) & 0x3F) ) { + single_byte_write_into_a_PCA9629( CH_FM_PLUS, gMot_cntl_order[ gMotor_count % 5 ], 0x26, 0x80 | ((gMotor_count / 5) & 0x1) ); + gMotor_count++; + } + +#define PI 3.14159265358979323846 + + float r; + float g; + float b; + float k; + float c; + + k = (2 * PI) / 300.0; + c = count; + +#if 0 + r = sin( k * (c + 0.0) ); + g = sin( k * (c + 100.0) ); + b = sin( k * (c + 200.0) ); + r = (0 < r) ? r * 255.0 : 0; + g = (0 < g) ? g * 255.0 : 0; + b = (0 < b) ? b * 255.0 : 0; +#else + r = (sin( k * (c + 0.0) ) + 1) * (127.5 * ((count < 500) ? (float)count / 500.0 : 1.0)); + g = (sin( k * (c + 100.0) ) + 1) * (127.5 * ((count < 500) ? (float)count / 500.0 : 1.0)); + b = (sin( k * (c + 200.0) ) + 1) * (127.5 * ((count < 500) ? (float)count / 500.0 : 1.0)); +#endif + for ( int i = 0; i < N_OF_LEDS; i += N_LED_PER_BOARD ) { + for ( int j = 0; j < 12; j += 3 ) { + gLEDs[ i + j + 0 ] = (char)r; + gLEDs[ i + j + 1 ] = (char)g; + gLEDs[ i + j + 2 ] = (char)b; + } + for ( int j = 12; j < 15; j ++ ) + gLEDs[ i + j ] = (char)((((2500 <= count) && (count < 3000)) ? ((float)(count - 2500) / 500.0) : 0.0) * 255.0); + } +} + +//void pattern_color_phase( int count ) { +void pattern_colors( int count ) { + + if ( !count ) { + gMotor_count = 0; + setup_transfer( CH_FM_PLUS, mot_norm_op_transfer, sizeof( mot_norm_op_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); // just update PCA9629 registers. no motor action + } + + if ( !((count + 20) & 0x3F) ) { + single_byte_write_into_a_PCA9629( CH_FM_PLUS, gMot_cntl_order[ gMotor_count % 5 ], 0x26, 0x80 | ((gMotor_count / 5) & 0x1) ); + gMotor_count++; + } + +#define PI 3.14159265358979323846 + + float p; + float k; + float c; + + k = (2 * PI) / 300.0; + p = 300.0 / N_OF_LEDS; + c = count; + + for ( int i = 0; i < N_OF_LEDS; i += N_LED_PER_BOARD ) { + for ( int j = 0; j < 12; j += 3 ) { + gLEDs[ i + j + 0 ] = (char)((sin( k * (c + 0.0) + p * (i + j) ) + 1) * (127.5 * ((count < 500) ? (float)count / 500.0 : 1.0))); + gLEDs[ i + j + 1 ] = (char)((sin( k * (c + 100.0) + p * (i + j) ) + 1) * (127.5 * ((count < 500) ? (float)count / 500.0 : 1.0))); + gLEDs[ i + j + 2 ] = (char)((sin( k * (c + 200.0) + p * (i + j) ) + 1) * (127.5 * ((count < 500) ? (float)count / 500.0 : 1.0))); + } + for ( int j = 12; j < 15; j ++ ) + gLEDs[ i + j ] = (char)((((2500 <= count) && (count < 3000)) ? ((float)(count - 2500) / 500.0) : 0.0) * 255.0); + } +} + + + + + +void pattern_one_by_one( int count ) { + if ( count == 0 ) { + all_LEDs_turn_off(); + return; + } + + gLEDs[ (count / 9) % N_OF_LEDS ] = nine_step_intensity[ count % 9 ]; +} + +void pattern_random( int count ) { + if ( count == 0 ) { + all_LEDs_turn_off(); + return; + } + gLEDs[ rand() % N_OF_LEDS ] = rand() % 0xFF; +} + +void pattern_random_with_decay0( int count ) { + if ( count == 0 ) { + all_LEDs_turn_off(); + return; + } + gLEDs[ rand() % N_OF_LEDS ] = 0xFF; + + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = (char)((float)gLEDs[ i ] * 0.90); +} + +void pattern_random_with_decay1( int count ) { + if ( count == 0 ) { + all_LEDs_turn_off(); + return; + } + gLEDs[ rand() % N_OF_LEDS ] = 0xFF; + + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = (char)((float)gLEDs[ i ] * 0.7); +} + +void pattern_flashing( int count ) { +#define SUSTAIN_DURATION 10 + static float interval; + static int timing; + static int sustain; + + if ( count == 0 ) { + interval = 100.0; + timing = 0; + sustain = SUSTAIN_DURATION; + vib_all_PCA9629(); + } + if ( (timing == count) || !((int)interval) ) { + sustain = SUSTAIN_DURATION; + all_LEDs_turn_on(); + start_all_PCA9629(); + + timing += (int)interval; + interval *= 0.96; + } else { + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = (char)((float)gLEDs[ i ] * 0.90); + + if ( sustain-- < 0 ) + stop_all_PCA9629(); + } +} + +void stop( int count ) { + if ( !count ) { + all_LEDs_turn_off(); + stop_all_PCA9629(); + } +} + +void pattern_init( int count ) { + + if ( !count ) + align_all_PCA9629(); +} + + +void pattern_scan( int count ) { + static char gMotor_count; + + if ( !count ) { + gMotor_count = 0; + setup_transfer( CH_FM_PLUS, mot_norm_op_transfer, sizeof( mot_norm_op_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); // just update PCA9629 registers. no motor action + } + + if ( !(count & 0x1F) ) { + single_byte_write_into_a_PCA9629( CH_FM_PLUS, gMot_cntl_order[ gMotor_count % 5 ], 0x26, 0x80 | ((gMotor_count / 5) & 0x1) ); + gMotor_count++; + } + + all_LEDs_turn_off(); + gLEDs[ (count >> 3) % N_OF_LEDS ] = 0xFF; +} + +void pattern_setup_half_turns( int count ) { + + if ( !count ) { + align_all_PCA9629(); + gMotor_count = 0; + } else if ( count == 50 ) { + setup_transfer( CH_FM_PLUS, mot_half_setup_transfer, sizeof( mot_half_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); + } else if ( count == 60 ) { + single_byte_write_into_a_PCA9629( CH_FM_PLUS, gMot_cntl_order[ 4 ], 0x26, 0x80 ); + } else if ( count == 75 ) { + single_byte_write_into_a_PCA9629( CH_FM_PLUS, gMot_cntl_order[ 3 ], 0x26, 0x80 ); + } else if ( count == 90 ) { + single_byte_write_into_a_PCA9629( CH_FM_PLUS, gMot_cntl_order[ 2 ], 0x26, 0x80 ); + } else if ( count == 115 ) { + single_byte_write_into_a_PCA9629( CH_FM_PLUS, gMot_cntl_order[ 1 ], 0x26, 0x80 ); + } else if ( count == 150 ) { + setup_transfer( CH_FM_PLUS, mot_half_transfer, sizeof( mot_half_transfer ) / sizeof( transaction ) ); + start( CH_FM_PLUS ); + } +} + + + +void pattern_half_turns( int count ) { + +#ifdef INTERVAL128MS + if ( !(count & 0x0F) ) { +#else + if ( !(count & 0x1F) ) { +#endif + if ( gMot_cntl_order_halfturn[ gMotor_count ] ) + single_byte_write_into_a_PCA9629( CH_FM_PLUS, gMot_cntl_order_halfturn[ gMotor_count ], 0x26, 0x80 | ((gMot_cntl_order_halfturn[ gMotor_count ] >> 1) & 0x1) ); + gMotor_count++; + + gMotor_count = (gMotor_count == 10) ? 0 : gMotor_count; + } + + +// all_LEDs_turn_off(); +// gLEDs[ (count >> 3) % N_OF_LEDS ] = 0xFF; +} + + + +void pattern_fadeout300( int count ) { + + if ( !count ) + stop_all_PCA9629(); + else if ( count == 100 ) + align_all_PCA9629(); + + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = (char)((float)gLEDs[ i ] * 0.994469); // (0.994469 = 1/(255^(1/999))) BUT VALUE IS TRANCATED IN THE LOOP. IT DECALYS FASTER THAN FLOAT CALC. +} + +void pattern_speed_variations( int count ) { + + char data[ 4 ]; + int v; + + if ( !count ) { + setup_transfer( CH_FM_PLUS, mot_norm_op_transfer, sizeof( mot_norm_op_transfer ) / sizeof( transaction ) ); + + data[ 0 ] = 0x2; + for ( int i = 0; i < 5; i++ ) + buffer_overwrite( CH_FM_PLUS, i, 20, data, 1 ); // Set half step operation + + for ( int i = 0; i < 5; i++ ) { + v = 833;// 400pps for halfstep + data[ 0 ] = data[ 2 ] = v & 0xFF; + data[ 1 ] = data[ 3 ] = (i << 5) | (v >> 8); + buffer_overwrite( CH_FM_PLUS, i, 23, data, 4 ); + } + + for ( int i = 0; i < 5; i++ ) { + v = (0x1 << (5 - i)); + data[ 0 ] = data[ 2 ] = v & 0xFF; + data[ 1 ] = data[ 3 ] = v >> 8; + buffer_overwrite( CH_FM_PLUS, i, 31, data, 4 ); + } + + + } + + if ( !(count % 500) ) { + data[ 0 ] = 0x84 | ((count / 500) & 0x1); + for ( int i = 0; i < 5; i++ ) + buffer_overwrite( CH_FM_PLUS, i, 39, data, 1 ); + start( CH_FM_PLUS ); + } +} + +void pattern_mot_ramp_variations( int count ) { + + char ramp_var[5][17] = { + { 0x5D, 0x03, 0x5D, 0x03, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x88 }, + { 0x4B, 0x05, 0x4B, 0x05, 0x25, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x88 }, + { 0x15, 0x06, 0x15, 0x06, 0x2D, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x88 }, + { 0x71, 0x06, 0x71, 0x06, 0x17, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x88 }, + { 0x9C, 0x06, 0x9C, 0x06, 0x23, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x88 }, + }; + + if ( !count ) { + setup_transfer( CH_FM_PLUS, mot_norm_op_transfer, sizeof( mot_norm_op_transfer ) / sizeof( transaction ) ); + + for ( int i = 0; i < 5; i++ ) + buffer_overwrite( CH_FM_PLUS, i, 23, ramp_var[ i ], 17 ); + + start( CH_FM_PLUS ); + } + + all_LEDs_turn_off(); + gLEDs[ count % N_OF_LEDS ] = 0xFF; + +} + +void pattern_knightrider( int count ) { + short led_pat[ 12 ] = { 0x7000, 0x0004, 0x0E00, 0x0002, 0x01C0, 0x0001, 0x0038, 0x0001, 0x01C0, 0x0002, 0x0E00, 0x0004 }; + short led_bits; + +#if 0 + //if ( !(count && 0x7) ) + { + led_bits = led_pat[ (count >> 4) % 12 ]; + for ( int i = 0; i < N_OF_LEDS; i += N_LED_PER_BOARD ) { + for ( int j = 0; j < N_LED_PER_BOARD; j ++ ) { + gLEDs[ i + j ] = ((led_bits << j) & 0x4000) ? 0xFF : gLEDs[ i + j ]; + } + } + } + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = (char)((float)gLEDs[ i ] * 0.90 * ((700 < count) ? (float)(1000 - count) / 300.0 : 1.0)); +#else + //if ( !(count && 0x7) ) + { + led_bits = led_pat[ (count >> 4) % 12 ]; + for ( int i = 0; i < N_OF_LEDS; i += N_LED_PER_BOARD ) { + for ( int j = 0; j < N_LED_PER_BOARD; j ++ ) { + gLEDs[ i + j ] = ((led_bits << j) & 0x4000) ? ((744 < count) ? (1000 - count) : 255) : gLEDs[ i + j ]; +// gLEDs[ i + j ] = ((led_bits << j) & 0x4000) ? 0xFF : gLEDs[ i + j ]; + } + } + } + for ( int i = 0; i < N_OF_LEDS; i++ ) + gLEDs[ i ] = (char)((float)gLEDs[ i ] * 0.90); +#endif + +} +pattern _gPt[] = { +// { 256, pattern_rampup }, + { 3000, pattern_colors }, +}; +pattern gPt[] = { +// { 256, pattern_rampup }, + { 20, stop }, + { 120, pattern_init }, + { 3000, pattern_colors }, + { 300, pattern_fadeout300 }, + { 3000, pattern_speed_variations }, + { 250, pattern_setup_half_turns }, + { 3000, pattern_half_turns }, + { 20, stop }, + { 120, pattern_init }, + { 960, pattern_rampup_and_down_w_color }, + { 960, pattern_scan }, + { 20, stop }, + { 120, pattern_init }, + { 1024, pattern_rampup_and_down }, + { 700, pattern_mot_ramp_variations }, + { 700, pattern_mot_ramp_variations }, + { 700, pattern_mot_ramp_variations }, + { 700, pattern_mot_ramp_variations }, + + { 3000, pattern_flashing }, + { 300, pattern_fadeout300 }, + { 512, pattern_random }, + { 512, pattern_random_with_decay1 }, + { 512, pattern_random_with_decay0 }, + { 9 * 120, pattern_one_by_one }, + { 1000, pattern_knightrider }, + +}; + + + +void pattern_update( int count ) { + static int next_pattern_change = 0; + static int local_count = 0; + static int pattern_index = -1; + + if ( next_pattern_change == count ) { + local_count = 0; + pattern_index++; + pattern_index = (pattern_index == (sizeof( gPt ) / sizeof( pattern )) ) ? 0 : pattern_index; + next_pattern_change += gPt[ pattern_index ].duration; + } + + (*gPt[ pattern_index ].pattern_func)( local_count++ ); +} +