mini board PCU9669 (and PCA9665) sample code

Dependencies:   mbed PCU9669 utility PCA9665 I2C_slaves parallel_bus

Fork of mini_board_PCU9669_old by InetrfaceProducts NXP

Sample code for PCU9669 (PCU9661, PCA9663, PCA9661 and PCA9665) evaluation board.

PCU9669 evaluation board: Mini board PCU9669
User manual is available -> http://www.nxp.com/documents/user_manual/UM10580.pdf

Revision:
5:57c345099873
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mini_board_libs/parallel_bus/hardware_abs.c	Mon Mar 26 06:17:23 2012 +0000
@@ -0,0 +1,220 @@
+/** A sample code for "mini board PCU9669/PCA9665"
+ *
+ *  @author  Tedd OKANO, NXP Semiconductors
+ *  @version 0.9
+ *  @date    14-Feb-2011
+ *
+ *  Released under the MIT License: http://mbed.org/license/mit
+ *
+ *  An operation sample of PCU9669/PCA9665 I2C bus controller.
+ *  The mbed accesses the bus controller's parallel port (8/2 bit address and 8 bit data) by bit-banging.
+ *  The bit-banging is poerformed by PortInOut function of mbed library.
+ *
+ *    To make the code porting easier, all codes are partitioned into layers to abstract other parts.
+ *    The mbed specific parts are concentrated in lowest layer: "hardware_abs.*".
+ *    This module may need to be modified for the porting.
+ *
+ *    All other upper layers are writen in standard-C.
+ *
+ *    base code is written from 05-Sep-2011 to 09-Sep-2011.
+ *    And demo code has been build on 11-Sep-2011.
+ *    Debug and code adjustment has been done on 08-Sep-2011.
+ *    Small sanitization for main.cpp. All mbed related codes are moved in to "hardware_abs.*". 13-Oct-2011
+ *    hardware_abs are moved into parallel_bus library folder, 3 LED driver operation sample 13-Feb.-2012
+ *    PCU9669 and PCA9665 codes are packed in a project 14-Feb-2012. 
+ *    
+ *    Before builidng the code, please edit the file mini_board_PCU9669/config.h
+ *    Uncomment the target name what you want to target. 
+ */
+
+/*
+ *  "hardware_abs" module has been made to abstract hardware: Hardware abstract layer
+ *  This is file which will be modified when the porting done for other MCUs. 
+ */
+ 
+/*
+ *  This sample code has been made for mbed. The code emulates parallel SRAM bus using the mbed's GPIO ports. 
+ *  To maximize the port access speed, PortOut and PortInOut libraly used. 
+ */
+
+#include    "mbed.h"
+#include    "hardware_abs.h"
+
+//  GPIO port setting
+
+#define     ADDR_MASK       0x07878000  //  8 bit address mask on PORT0: Address value will be set into this bit position
+#define     DATA_MASK       0x00000FF0  //  8 bit data mask on PORT0: Data value will be appeared on this bit position
+#define     CONTROL_MASK    0x00000038  //  Control signals CS=bit5(pin21), WR=bit4(pin22), RD=bit3(pin23)
+
+PortOut     addr_port( Port0, ADDR_MASK );
+PortInOut   data_port( Port0, DATA_MASK );
+PortOut     ctrl_port( Port2, CONTROL_MASK );
+InterruptIn int_port( p26 );
+
+//  The very early version of PCU9669 mini board has different configuration. 
+//  Following part switches the port configuration for those board versions.
+
+//#define     PROTOTYPE_BREADBOARD
+
+DigitalInOut    reset_port( p20 );
+//DigitalOut      trig_port( p19 );
+
+//  Next two macros defines interface for temporaly interrupt disable/enable functions. 
+//  These macros are used to blocking interrupt until a bus access cycle completed.
+//  Because if the interrupt happened in a cycle, the emulated parallel port state will be disturbed.  
+//  For the mbed, library routine: __disable_irq() / __enable_irq() can be used. 
+
+#define     interrupt_enable()    __enable_irq()
+#define     interrupt_disable()   __disable_irq()
+
+//  "prev_access_was_write" is a variable to keep the previous data directions. 
+//  Using this flag, successive write and read addess overhead can be reduced. 
+//  This mechanism will not be required if the MCU has parallel port
+
+char        prev_access_was_write;
+
+//  ISR routine installer
+
+void install_ISR( void (*fptr)(void) ) {
+    int_port.fall( fptr );
+}
+
+//  Hardware initialize: it defines initial state of the (emulated) parallel bus
+
+void hardware_initialize( void ) {
+    prev_access_was_write   = 0;
+    ctrl_port               = 0x38;     //  CS, WR and RD are deaserted (HIGH)
+    data_port.input();                  //  data bus set to Hi-Z
+    reset_port.output();
+    reset_port.mode( PullUp );
+}
+
+//  Hardware reset for PCU9669: It asserts RESET signal for 4us and waits 650us after deassert (reset recovery time)
+
+void reset( int reset_pulse_width_us, int reset_recovery_us ) {
+    hardware_reset( ASSERT );            //  Minimum pulse width is 4us for PCU9669
+    hw_wait_us( reset_pulse_width_us );
+    hardware_reset( DEASSERT );          //  deassert hardware /RESET sgnal
+    hw_wait_us( reset_recovery_us );
+}
+
+//  Interface to Control hardware RESET signal
+
+void hardware_reset( char signal ) {
+    reset_port  = signal;
+}
+
+//  Interface to Control hardware TRIGGER signal
+
+void hardware_trigger( char signal ) {
+//    trig_port  = signal;
+}
+
+//  Single write cycle on (emulated) parallel bus
+
+void write_data( char addr, char data ) {
+    interrupt_disable();    //  disable interrupt first
+
+    addr_port   = (addr << 19) | (addr << 15);  //  Address output
+    ctrl_port   = 0x08;                         //  Assert CS and WR signals
+
+    if ( !prev_access_was_write )               //  Data bus direction control
+        data_port.output();
+
+    prev_access_was_write  = 1;
+
+    data_port   = data << 4;                    //  Data output
+    ctrl_port   = 0x38;                         //  Deassert CS and WR
+
+    interrupt_enable();    //  enable interrupt again
+}
+
+
+char read_data( char addr ) {
+    volatile char    tmp;
+    interrupt_disable();    //  disable interrupt first
+
+    if ( prev_access_was_write )    //  Data bus direction control
+        data_port.input();
+
+    prev_access_was_write  = 0;
+
+    addr_port   = (addr << 19) | (addr << 15);  //  Address output
+    ctrl_port   = 0x10;                         //  Assert CS and RD signals
+    ctrl_port   = 0x10;                         //  asserting CS and RD pulse twice (but those are kept LOW) to wait short time till actual read timing
+    tmp         = (data_port >> 4) & 0xFF;      //  Read data bus into var
+    ctrl_port   = 0x38;                         //  Deassert CS and RD
+
+    interrupt_enable();    //  enable interrupt again
+
+    return ( tmp );
+}
+
+//  Wait for micro-seconds
+
+void hw_wait_us( int v ) {
+    wait_us( v );
+}
+
+//  Wait for seconds
+
+void wait_sec( float f ) {
+    wait( f );
+}
+
+//  Following part is an optionto accerelate bus access. 
+//  If such trick is not required, undefine the "BURST_DATA_ACCESS" and don't touch it.
+//
+//  Next two functions access single address with repeating read/write. 
+//  The repeating read/write are used often for PCU9669 like SLATABLE, TRANCONFIG and DATA (buffer accesses). 
+//  So this accerelation contributes saving MCU time. 
+//
+//  For the porting, it may be good idea to modify those routines to DMA access. 
+
+#ifdef  BURST_DATA_ACCESS
+
+void write_data_burst( char addr, char *data, char length ) {
+    int     i;
+
+    interrupt_disable();    //  disable interrupt first
+
+    addr_port   = (addr << 19) | (addr << 15);  //  Address output
+
+    if ( !prev_access_was_write )       //  Data bus direction control
+        data_port.output();
+
+    prev_access_was_write  = 1;
+
+    for ( i = 0; i < length; i++ ) {    //  repeat data write access
+        ctrl_port   = 0x08;
+        data_port   = *(data + i) << 4;
+        ctrl_port   = 0x38;
+    }
+
+    interrupt_enable();
+}
+
+void read_data_burst( char addr, char *data, char length ) {
+    int     i;
+
+    interrupt_disable();    //  disable interrupt first
+
+    addr_port   = (addr << 19) | (addr << 15);  //  Address output
+
+    if ( prev_access_was_write )       //  Data bus direction control
+        data_port.input();
+
+    prev_access_was_write  = 0;
+
+    for ( i = 0; i < length; i++ ) {    //  repeat data read access
+        ctrl_port   = 0x10;
+        ctrl_port   = 0x10;
+
+        *(data + i) = (data_port >> 4) & 0xFF;
+        ctrl_port   = 0x38;
+    }
+    interrupt_enable();
+}
+
+#endif
+