/*
 * i2c_pcal64xx.h
 *
 *  Created on: May 3, 2024
 *      Author: tm
 *
 *   Support for pcal6416 and pcal6408a
 */

#ifndef I2C_PCAL64XX_H_
#define I2C_PCAL64XX_H_


int pcal6416_spec_pwr(int state);
int pcal6416_lamp_pwr(int state);
int pcal6416_deuterium(int state);
int pcal6416_tungsten(int state);

int pcal6416_probe(uint8_t i2cAddr);
void pcal6416_test(int testNum);
void pcal6416_test_menu(void);
int pcal6416_init(void);
int pcal6416_reset(void);
int pcal6416_read(uint8_t reg_addr, uint8_t *data, uint8_t byteCnt);
int pcal6416_write_byte(uint8_t reg_addr, uint8_t device_data);
int pcal6416_read_byte(uint8_t reg_addr, uint8_t *data);
int pcal6416_write(uint8_t reg_addr, uint8_t *data, uint8_t length);

int pcal6416_write_default(void);
int pcal6416_start(void);
int pcal6416_stop(void);
int pcal6416_read8_port(uint32_t portNum, uint8_t *data);
int pcal6416_read16_port(uint32_t portNum, uint8_t *data0, uint8_t *data1);
int pcal6416_write8_port(uint32_t portNum, uint8_t data);
int pcal6416_write1_port(uint32_t portNum, uint8_t bitNum, uint32_t state);
int pcal6416_write_port_bit(uint8_t regNum, uint8_t bitMask, uint32_t state);

int pcal6408_probe(void);
int pcal6408_test(void);
int pcal6408_init(void);
int pcal6408_reset(void);
int pcal6408_write_default(void);
int pcal6408_start(void);
int pcal6408_stop(void);
int pcal6408_read8_port(uint32_t portNum, uint8_t *data);
int pcal6408_write8_port(uint32_t portNum, uint8_t data);
int pcal6408_write1_port(uint32_t portNum, uint8_t bitNum, uint32_t state);

// https://github.com/SolderedElectronics/Soldered-PCAL6416A-IO-Expander-Arduino-Library/blob/main/src/PCAL6416A-SOLDERED.h


//Following the successful acknowledgment of I2C addr, controller sends a command byte, stored in the Pointer register in the PCAL6416A

#ifdef APFTODO
//Outputs
Spec_Pwr
Pump_Pwr
Lamp_Pwr
Lamp_D
Lamp_W
Lamp_Shutter
//Inputs
VsysLow
Spec_Pwr_Fdbk
Pump_Pwr_Fdbk
Lamp_Pwr_Fdbk
Lamp_Ctr_Alarm
#endif

//#define SPEC_PWR_BIT            0x02
//#define APF_ERROR               ()-1)

//#if BOARD_MSC == 2
// IO_PORT_0 OUTPUTS
#define SPEC_PWR_ON              0x01
#define PUMP_PWR_ON              0x02
#define LAMP_PWR_ON              0x04
#define LAMP_DU_ENABLE           0x08
#define LAMP_W_ENABLE            0x10
#define LAMP_SHUT_ENABLE         0x20
#define SPEC_232_EN              0x40       //PCAL6416_SPARE1          0x40
#define PCAL6416_SPARE2          0x80

#ifdef NOCODE
#define DURA_PWR_ON              0x01       // no longer used in MSC3
#define SPEC_PWR_ON              0x02
#define REFD_PWR_ON              0x04
#define PUMP_PWR_ON              0x08
#define LAMP_PWR_ON              0x10
#define LAMP_DU_ENABLE           0x20
#define LAMP_W_ENABLE            0x40
#define LAMP_SHUT_ENABLE         0x80
#endif
// IO_PORT_1 INPUTS
#define PCAL6416_SPARE3          0x01
#define PCAL6416_SPARE4          0x02
#define PCAL6416_SPARE5          0x04
#define VSYSLOW                  0x08
#define SPEC_PWR_FDBK            0x10
#define PUMP_PWR_FDBK            0x20
#define LAMP_PWR_FDBK            0x40
#define LAMP_CTR_ALARM           0x80

#ifdef NOCODE
#define DURA_PWR_FDBK            0x01
#define SPEC_PWR_FDBK            0x02
#define REFD_PWR_FDBK            0x04
#define PUMP_PWR_FDBK            0x08
#define LAMP_PWR_FDBK            0x10
#define LAMP_CTR_ALARM           0x20
#define TH_HI_ALARM              0x40
#define TH_LO_ALARM              0x80
#endif


//#endif

#if BOARD_MSC == 3
#define SPEC_PWR_ON              0x01
#define PUMP_PWR_ON              0x02
#define LAMP_PWR_ON              0x04
#define LAMP_DU_ENABLE           0x08
#define LAMP_W_ENABLE            0x10
#define LAMP_SHUT_ENABLE         0x20       // no longer used in MSC3
#define IO_SPARE1                0x40
#define IO_SPARE2                0x80
// IO_PORT_1
#define IO_SPARE3                0x01
#define IO_SPARE4                0x02
#define IO_SPARE5                0x04
#define VSYSLOW                  0x08
#define SPEC_PWR_FDBK            0x10
#define PUMP_PWR_FDBK            0x20
#define LAMP_PWR_FDBK            0x40
#define LAMP_CTR_ALARM           0x80
#endif

#define PCAL6416_I2C_ADDR          0x20  //0x40        // I2C bus address (7bit: 0x20/0x21)
//#define PCAL6416_CHIPID_VAL                       // does not appear to have CHIP ID
// PCAL6416A Register map, Command byte
#define PCAL6416A_IN_PORT0          0x00
#define PCAL6416A_IN_PORT1          0x01
#define PCAL6416A_OUT_PORT0         0x02        //PCAL6416_OUTPUT_PORT0
#define PCAL6416A_OUT_PORT1         0x03
#define PCAL6416A_POL_INV0          0x04
#define PCAL6416A_POL_INV1          0x05
#define PCAL6416A_CONFIG0           0x06
#define PCAL6416A_CONFIG1           0x07
#define PCAL6416A_OUT_DRV0          0x40
#define PCAL6416A_OUT_DRV1          0x41
#define PCAL6416A_OUT_DRV2          0x42
#define PCAL6416A_OUT_DRV3          0x43
#define PCAL6416A_IN_LATCH0         0x44
#define PCAL6416A_IN_LATCH1         0x45
#define PCAL6416A_PUPDEN0           0x46        //PULL_UP_DOWN_EN
#define PCAL6416A_PUPDEN1           0x47
#define PCAL6416A_PUPDSEL0          0x48        // PULL_UP_DOWN_SEL
#define PCAL6416A_PUPDSEL1          0x49
#define PCAL6416A_INTMSK0           0x4A
#define PCAL6416A_INTMSK1           0x4B
#define PCAL6416A_INTSTAT0          0x4C
#define PCAL6416A_INTSTAT1          0x4D
#define PCAL6416A_OUTPORT_CONFIG    0x4F


#define PCAL6416A_A0 0
#define PCAL6416A_A1 1
#define PCAL6416A_A2 2
#define PCAL6416A_A3 3
#define PCAL6416A_A4 4
#define PCAL6416A_A5 5
#define PCAL6416A_A6 6
#define PCAL6416A_A7 7
#define PCAL6416A_B0 8
#define PCAL6416A_B1 9
#define PCAL6416A_B2 10
#define PCAL6416A_B3 11
#define PCAL6416A_B4 12
#define PCAL6416A_B5 13
#define PCAL6416A_B6 14
#define PCAL6416A_B7 15

#define INPUT_PULLDOWN 3

// Very similar to PCA953x

// from nordic
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_nrf5_v17.0.2%2Fgroup__pcal6408a__driver.html

//#define PCAL6408A_BASE_ADDRESS         0x21  // 0x42    //A0=1 (7bit 0x21)
#define PCAL6408A_I2C_ADDR          0x21

#define PCAL6408A_IN_PORT           0x00
#define PCAL6408A_OUT_PORT          0x01
#define PCAL6408A_POL_INV           0x02
#define PCAL6408A_CONFIG            0x03
#define PCAL6408A_OUT_DRV0          0x40
#define PCAL6408A_OUT_DRV1          0x41
#define PCAL6408A_IN_LATCH          0x42
#define PCAL6408A_PUPDEN            0x43
#define PCAL6408A_PUPDSEL           0x44
#define PCAL6408A_INTMASK           0x45
#define PCAL6408A_INTSTATUS         0x46
#define PCAL6408A_OUTPORT_CONFIG    0x4F


#define PCAL6408A_PIN_DIR_OUT           0x00
#define PCAL6408A_PIN_DIR_IN            0x01

#define PCAL6408A_PORT_DIR_OUT          0x00
#define PCAL6408A_PORT_DIR_IN           0xFF

#define PCAL6408A_PIN_CLR               0x00
#define PCAL6408A_PIN_SET               0x01

#define PCAL6408A_PIN_NOPULL            0x00
#define PCAL6408A_PIN_PULLDOWN          0x01
#define PCAL6408A_PIN_PULLUP            0x02


#define PCAL6408A_PORT_WRITE            0x00
#define PCAL6408A_PORT_CLEAR            0x01
#define PCAL6408A_PORT_SET              0x02


#define PCAL6408A_PIN_25_DRV_STREN      0x00
#define PCAL6408A_PIN_50_DRV_STREN      0x01
#define PCAL6408A_PIN_75_DRV_STREN      0x02
#define PCAL6408A_PIN_100_DRV_STREN     0x03

#define PCAL6408A_PORT_PUSH_PULL        0x00
#define PCAL6408A_PORT_OPEN_DRAIN       0x01

#define PCAL6408_OUTPUT_REG             0x01
#define PCAL6408_CONFIGURATION_REG      0x03


#ifdef OLDCF2CODE


// PCAL6416 COMMAND BYTE REGISTER ADDRESSES
#define PCAL6416_INPUT_PORT0     0x00
#define PCAL6416_INPUT_PORT1     0x01
#define PCAL6416_OUTPUT_PORT0    0x02
#define PCAL6416_OUTPUT_PORT1    0x03
#define PCAL6416_INVERT_REG0     0x04
#define PCAL6416_INVERT_REG1     0x05
#define PCAL6416_CONFIG_REG0     0x06
#define PCAL6416_CONFIG_REG1     0x07
#define PCAL6416_DRIVE_REG0      0x40
#define PCAL6416_DRIVE_REG1      0x41
#define PCAL6416_DRIVE_REG2      0x42
#define PCAL6416_DRIVE_REG3      0x43
#define PCAL6416_LATCH_REG0      0x44
#define PCAL6416_LATCH_REG1      0x45
#define PCAL6416_PULLENB_REG0    0x46
#define PCAL6416_PULLENB_REG1    0x47
#define PCAL6416_PULLDIR_REG0    0x48
#define PCAL6416_PULLDIR_REG1    0x49
#define PCAL6416_INTMASK_REG0    0x4A
#define PCAL6416_INTMASK_REG1    0x4B
#define PCAL6416_INTSTAT_REG0    0x4C
#define PCAL6416_INTSTAT_REG1    0x4D
#define PCAL6416_OUTCONFIG_REG   0x4F

// PCAL6416 DEFAULT OUTPUT PORT DATA VALUES
#define PCAL6416_OUTPUT_VAL0     0x00
#define PCAL6416_OUTPUT_VAL1     0x00

// PCAL6416 DEFAULT INVERT PORT BYTE VALUES
#define PCAL6416_INVERT_VAL0     0x00               //disable all inversion
#define PCAL6416_INVERT_VAL1     0x00               //disable all inversion

// PCAL6416 DEFAULT CONFIG PORT BYTE VALUES  (PIN DATA DIRECTION)
#define PCAL6416_CONFIG_VAL0     0x00               //set to outputs
#define PCAL6416_CONFIG_VAL1     0xFF               //set to inputs

// PCAL6416 DEFAULT PULL-UP/DOWN ENABLE VALUES
#define PCAL6416_PULLENB_VAL0    0x00               //disable pull-up/down resistors on port 0
#define PCAL6416_PULLENB_VAL1    0xFF               //enable  pull-up/down resistros on port 1

// PCAL6416 DEFAULT OUTPUT PORT CONFIGURATION VALUE (PUSH-PULL OR OPEN-DRAIN)
#define PCAL6416_OUTCONFIG_VAL   0x00               //set to push-pull, per datasheet this value should be set prior to writing to the config regs

// PCAL6416 READ REGISTER OFFSET FROM ASSOCIATED WRITE REGISTER
#define PCAL6416_RD_OFFSET       0x02

// PCAL6416 APF CONTROLLER BOARD PIN ASSIGNMENTS
// IO_PORT_0
#define DURA_PWR_ON              0x01
#define SPEC_PWR_ON              0x02
#define REFD_PWR_ON              0x04
#define PUMP_PWR_ON              0x08
#define LAMP_PWR_ON              0x10
#define LAMP_DU_ENABLE           0x20
#define LAMP_W_ENABLE            0x40
#define LAMP_SHUT_ENABLE         0x80
// IO_PORT_1
#define DURA_PWR_FDBK            0x01
#define SPEC_PWR_FDBK            0x02
#define REFD_PWR_FDBK            0x04
#define PUMP_PWR_FDBK            0x08
#define LAMP_PWR_FDBK            0x10
#define LAMP_CTR_ALARM           0x20
#define TH_HI_ALARM              0x40
#define TH_LO_ALARM              0x80
#endif

#endif /* I2C_PCAL64XX_H_ */
