demo sample to drive PCU9955 and PCA9629

Dependencies:   mbed I2C_slaves PCU9669 parallel_bus

Fork of mini_board_PCU9669 by InetrfaceProducts NXP

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.

/media/uploads/nxp_ip/dsc_0414ss.png
Demo setup
(left-top: PCU9955 boards, left-bottom: mini-board PCU9669 with mbed, right: PCA9629 x5 board)

/media/uploads/nxp_ip/demo-config-ss.png
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)

Revision:
21:3b75b545ecfb
Parent:
20:a266fa588bd8
--- a/demo_patterns.cpp	Fri Oct 26 05:59:55 2012 +0000
+++ b/demo_patterns.cpp	Fri Oct 26 07:03:47 2012 +0000
@@ -1,716 +1,750 @@
-#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++ );
-}
-
+#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;
+    float   f;
+
+    k   = (2 * PI) / 300.0;
+    c   = count;
+    f   = 127.5 * ((count < 500) ? (float)count / 500.0 : 1.0);
+
+#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) * f;
+    g   = (sin( k * (c + 100.0) ) + 1) * f;
+    b   = (sin( k * (c + 200.0) ) + 1) * f;
+#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;
+    float   f;
+
+    k   = (2 * PI) / 300.0;
+    p   = 300.0 / N_OF_LEDS;
+    c   = count;
+    f   = 127.5 * ((count < 500) ? c / 500.0 : 1.0);
+
+    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) * f);
+            gLEDs[ i + j + 1 ] = (char)((sin( k * (c + 100.0) + p * (i + j) ) + 1) * f);
+            gLEDs[ i + j + 2 ] = (char)((sin( k * (c + 200.0) + p * (i + j) ) + 1) * f);
+        }
+        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++ );
+}
+