From dad38bb220db312f047d1b20009f083f38f0f5fa Mon Sep 17 00:00:00 2001 From: mvturnho Date: Fri, 24 May 2019 16:17:15 +0200 Subject: [PATCH] added ANALOG_OUTPUT as first functionality --- esphome/components/sx1509/__init__.py | 20 ++ esphome/components/sx1509/output.py | 24 +++ esphome/components/sx1509/sx1509.cpp | 213 +++++++++++++++++++ esphome/components/sx1509/sx1509.h | 102 +++++++++ esphome/components/sx1509/sx1509_registers.h | 138 ++++++++++++ 5 files changed, 497 insertions(+) create mode 100644 esphome/components/sx1509/__init__.py create mode 100644 esphome/components/sx1509/output.py create mode 100644 esphome/components/sx1509/sx1509.cpp create mode 100644 esphome/components/sx1509/sx1509.h create mode 100644 esphome/components/sx1509/sx1509_registers.h diff --git a/esphome/components/sx1509/__init__.py b/esphome/components/sx1509/__init__.py new file mode 100644 index 0000000000..99b6c08272 --- /dev/null +++ b/esphome/components/sx1509/__init__.py @@ -0,0 +1,20 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c +from esphome.const import CONF_FREQUENCY, CONF_ID + +DEPENDENCIES = ['i2c'] +MULTI_CONF = True + +sx1509_ns = cg.esphome_ns.namespace('sx1509') +SX1509Component = sx1509_ns.class_('SX1509Component', cg.Component, i2c.I2CDevice) + +CONFIG_SCHEMA = cv.Schema({ + cv.GenerateID(): cv.declare_id(SX1509Component), +}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x3E)) + + +def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + yield cg.register_component(var, config) + yield i2c.register_i2c_device(var, config) diff --git a/esphome/components/sx1509/output.py b/esphome/components/sx1509/output.py new file mode 100644 index 0000000000..1200db54e6 --- /dev/null +++ b/esphome/components/sx1509/output.py @@ -0,0 +1,24 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import output +from esphome.const import CONF_CHANNEL, CONF_ID +from . import SX1509Component, sx1509_ns + +DEPENDENCIES = ['sx1509'] + +SX1509FloatOutputChannel = sx1509_ns.class_('SX1509FloatOutputChannel', output.FloatOutput) +CONF_SX1509_ID = 'sx1509_id' + +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ + cv.Required(CONF_ID): cv.declare_id(SX1509FloatOutputChannel), + cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component), + + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15), +}) + + +def to_code(config): + paren = yield cg.get_variable(config[CONF_SX1509_ID]) + rhs = paren.create_float_output_channel(config[CONF_CHANNEL]) + var = cg.Pvariable(config[CONF_ID], rhs) + yield output.register_output(var, config) diff --git a/esphome/components/sx1509/sx1509.cpp b/esphome/components/sx1509/sx1509.cpp new file mode 100644 index 0000000000..a52de4cfcc --- /dev/null +++ b/esphome/components/sx1509/sx1509.cpp @@ -0,0 +1,213 @@ +#include "sx1509.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace sx1509 { + +static const char *TAG = "sx1509"; + +void SX1509Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up SX1509ComponentComponent..."); + + ESP_LOGV(TAG, " Resetting devices..."); + this->write_byte(REG_RESET, 0x12); + this->write_byte(REG_RESET, 0x34); + + // Communication test. + uint16_t data; + this->read_byte_16(REG_INTERRUPT_MASK_A, &data); + if (data == 0xFF00) { + clock(INTERNAL_CLOCK_2MHZ); + } else { + this->mark_failed(); + return; + } + + for (auto *channel : this->float_output_channels_) + channel->setup_channel(); + + delayMicroseconds(500); + + this->loop(); +} + +void SX1509Component::dump_config() { + ESP_LOGCONFIG(TAG, "SX1509:"); + if (this->is_failed()) { + ESP_LOGE(TAG, "Setting up SX1509 failed!"); + } +} + +void SX1509Component::loop() {} + +SX1509FloatOutputChannel * +SX1509Component::create_float_output_channel(uint8_t channel) { + ESP_LOGD(TAG, "Set pin mode for channel %d", channel); + auto *c = new SX1509FloatOutputChannel(this, channel); + float_output_channels_.push_back(c); + return c; +} + +void SX1509Component::digitalWrite(uint8_t channel, uint8_t highLow) { + uint16_t tempRegDir = 0; + this->read_byte_16(REG_DIR_B, &tempRegDir); + + if ((0xFFFF ^ tempRegDir) & + (1 << channel)) // If the pin is an output, write high/low + { + uint16_t tempRegData = 0; + this->read_byte_16(REG_DATA_B, &tempRegData); + if (highLow) + tempRegData |= (1 << channel); + else + tempRegData &= ~(1 << channel); + this->write_byte_16(REG_DATA_B, tempRegData); + } else // Otherwise the pin is an input, pull-up/down + { + uint16_t tempPullUp; + this->read_byte_16(REG_PULL_UP_B, &tempPullUp); + uint16_t tempPullDown; + this->read_byte_16(REG_PULL_DOWN_B, &tempPullDown); + + if (highLow) // if HIGH, do pull-up, disable pull-down + { + tempPullUp |= (1 << channel); + tempPullDown &= ~(1 << channel); + this->write_byte_16(REG_PULL_UP_B, tempPullUp); + this->write_byte_16(REG_PULL_DOWN_B, tempPullDown); + } else // If LOW do pull-down, disable pull-up + { + tempPullDown |= (1 << channel); + tempPullUp &= ~(1 << channel); + this->write_byte_16(REG_PULL_UP_B, tempPullUp); + this->write_byte_16(REG_PULL_DOWN_B, tempPullDown); + } + } +} + +void SX1509Component::pinMode(uint8_t channel, uint8_t inOut) { + // The SX1509 RegDir registers: REG_DIR_B, REG_DIR_A + // 0: IO is configured as an output + // 1: IO is configured as an input + uint8_t modeBit; + if ((inOut == OUTPUT) || (inOut == ANALOG_OUTPUT)) + modeBit = 0; + else + modeBit = 1; + + uint16_t tempRegDir = 0; + this->read_byte_16(REG_DIR_B, &tempRegDir); + + if (modeBit) + tempRegDir |= (1 << channel); + else + tempRegDir &= ~(1 << channel); + + this->write_byte_16(REG_DIR_B, tempRegDir); + + // If INPUT_PULLUP was called, set up the pullup too: + if (inOut == INPUT_PULLUP) + digitalWrite(channel, HIGH); + + if (inOut == ANALOG_OUTPUT) { + ledDriverInit(channel); + } +} + +void SX1509Component::ledDriverInit(uint8_t channel, uint8_t freq, bool log) { + uint16_t tempWord; + uint8_t tempByte; + + // Disable input buffer + // Writing a 1 to the pin bit will disable that pins input buffer + this->read_byte_16(REG_INPUT_DISABLE_B, &tempWord); + tempWord |= (1 << channel); + this->write_byte_16(REG_INPUT_DISABLE_B, tempWord); + + // Disable pull-up + // Writing a 0 to the pin bit will disable that pull-up resistor + this->read_byte_16(REG_PULL_UP_B, &tempWord); + tempWord &= ~(1 << channel); + this->write_byte_16(REG_PULL_UP_B, tempWord); + + // Set direction to output (REG_DIR_B) + this->read_byte_16(REG_DIR_B, &tempWord); + tempWord &= ~(1 << channel); // 0=output + this->write_byte_16(REG_DIR_B, tempWord); + + // Enable oscillator (REG_CLOCK) + this->read_byte(REG_CLOCK, &tempByte); + tempByte |= (1 << 6); // Internal 2MHz oscillator part 1 (set bit 6) + tempByte &= ~(1 << 5); // Internal 2MHz oscillator part 2 (clear bit 5) + this->write_byte(REG_CLOCK, tempByte); + + // Configure LED driver clock and mode (REG_MISC) + this->read_byte(REG_MISC, &tempByte); + if (log) { + tempByte |= (1 << 7); // set logarithmic mode bank B + tempByte |= (1 << 3); // set logarithmic mode bank A + } else { + tempByte &= ~(1 << 7); // set linear mode bank B + tempByte &= ~(1 << 3); // set linear mode bank A + } + + // Use configClock to setup the clock divder + if (_clkX == 0) // Make clckX non-zero + { + _clkX = 2000000.0 / (1 << (1 - 1)); // Update private clock variable + + byte freq = (1 & 0x07) << 4; // freq should only be 3 bits from 6:4 + tempByte |= freq; + } + this->write_byte(REG_MISC, tempByte); + + // Enable LED driver operation (REG_LED_DRIVER_ENABLE) + this->read_byte_16(REG_LED_DRIVER_ENABLE_B, &tempWord); + tempWord |= (1 << channel); + this->write_byte_16(REG_LED_DRIVER_ENABLE_B, tempWord); + + // Set REG_DATA bit low ~ LED driver started + this->read_byte_16(REG_DATA_B, &tempWord); + tempWord &= ~(1 << channel); + this->write_byte_16(REG_DATA_B, tempWord); +} + +void SX1509Component::clock(byte oscSource, byte oscPinFunction, + byte oscFreqOut, byte oscDivider) { + oscSource = (oscSource & 0b11) << 5; // 2-bit value, bits 6:5 + oscPinFunction = (oscPinFunction & 1) << 4; // 1-bit value bit 4 + oscFreqOut = (oscFreqOut & 0b1111); // 4-bit value, bits 3:0 + byte regClock = oscSource | oscPinFunction | oscFreqOut; + this->write_byte(REG_CLOCK, regClock); + + oscDivider = constrain(oscDivider, 1, 7); + _clkX = 2000000.0 / (1 << (oscDivider - 1)); // Update private clock variable + oscDivider = (oscDivider & 0b111) << 4; // 3-bit value, bits 6:4 + + uint8_t regMisc; + this->read_byte(REG_MISC, ®Misc); + regMisc &= ~(0b111 << 4); + regMisc |= oscDivider; + this->write_byte(REG_MISC, regMisc); +} + +void SX1509Component::set_channel_value_(uint8_t channel, uint8_t iOn) { + ESP_LOGD(TAG, "set_channel_value_ for channel %d to %d", channel, iOn); + this->write_byte(REG_I_ON[channel], iOn); +} + +void SX1509FloatOutputChannel::write_state(float state) { + ESP_LOGD(TAG, "write_state %f", state); + const uint16_t max_duty = 255; + const float duty_rounded = roundf(state * max_duty); + auto duty = static_cast(duty_rounded); + this->parent_->set_channel_value_(this->channel_, duty); +} + +void SX1509FloatOutputChannel::setup_channel() { + this->parent_->pinMode(this->channel_, ANALOG_OUTPUT); +} + +} // namespace sx1509 +} // namespace esphome diff --git a/esphome/components/sx1509/sx1509.h b/esphome/components/sx1509/sx1509.h new file mode 100644 index 0000000000..a6e11fd3bc --- /dev/null +++ b/esphome/components/sx1509/sx1509.h @@ -0,0 +1,102 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/output/float_output.h" +#include "esphome/core/component.h" +#include "sx1509_registers.h" + +namespace esphome { +namespace sx1509 { + +// These are used for setting LED driver to linear or log mode: +#define LINEAR 0 +#define LOGARITHMIC 1 + +// These are used for clock config: +#define INTERNAL_CLOCK_2MHZ 2 +#define EXTERNAL_CLOCK 1 + +#define SOFTWARE_RESET 0 +#define HARDWARE_RESET 1 + +#define ANALOG_OUTPUT 0x3 // To set a pin mode for PWM output + +class SX1509Component; + +class SX1509FloatOutputChannel : public output::FloatOutput { +public: + SX1509FloatOutputChannel(SX1509Component *parent, uint8_t channel) + : parent_(parent), channel_(channel) {} + void setup_channel(); + +protected: + void write_state(float state) override; + + SX1509Component *parent_; + uint8_t channel_; +}; + +/// SX1509 float output component. +class SX1509Component : public Component, public i2c::I2CDevice { + +public: + SX1509Component() {} + + SX1509FloatOutputChannel *create_float_output_channel(uint8_t channel); + + void setup() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::HARDWARE; } + void loop() override; + +protected: + friend SX1509FloatOutputChannel; + std::vector float_output_channels_{}; + + void pinMode(uint8_t channel, uint8_t inOut); + void ledDriverInit(uint8_t channel, uint8_t freq = 1, bool log = false); + void clock(uint8_t oscSource = 2, uint8_t oscDivider = 1, + uint8_t oscPinFunction = 0, uint8_t oscFreqOut = 0); + void digitalWrite(uint8_t channel, uint8_t highLow); + void set_channel_value_(uint8_t channel, uint8_t iOn); + + // Pin definitions: + uint8_t pinInterrupt_; + uint8_t pinOscillator_; + uint8_t pinReset_; + // variables: + u_long _clkX; + uint8_t frequency_ = 0; + + bool update_{true}; + + byte REG_I_ON[16] = {REG_I_ON_0, REG_I_ON_1, REG_I_ON_2, REG_I_ON_3, + REG_I_ON_4, REG_I_ON_5, REG_I_ON_6, REG_I_ON_7, + REG_I_ON_8, REG_I_ON_9, REG_I_ON_10, REG_I_ON_11, + REG_I_ON_12, REG_I_ON_13, REG_I_ON_14, REG_I_ON_15}; + + byte REG_T_ON[16] = {REG_T_ON_0, REG_T_ON_1, REG_T_ON_2, REG_T_ON_3, + REG_T_ON_4, REG_T_ON_5, REG_T_ON_6, REG_T_ON_7, + REG_T_ON_8, REG_T_ON_9, REG_T_ON_10, REG_T_ON_11, + REG_T_ON_12, REG_T_ON_13, REG_T_ON_14, REG_T_ON_15}; + + byte REG_OFF[16] = {REG_OFF_0, REG_OFF_1, REG_OFF_2, REG_OFF_3, + REG_OFF_4, REG_OFF_5, REG_OFF_6, REG_OFF_7, + REG_OFF_8, REG_OFF_9, REG_OFF_10, REG_OFF_11, + REG_OFF_12, REG_OFF_13, REG_OFF_14, REG_OFF_15}; + + byte REG_T_RISE[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, + REG_T_RISE_4, REG_T_RISE_5, REG_T_RISE_6, REG_T_RISE_7, + 0xFF, 0xFF, 0xFF, 0xFF, + REG_T_RISE_12, REG_T_RISE_13, REG_T_RISE_14, REG_T_RISE_15}; + + byte REG_T_FALL[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, + REG_T_FALL_4, REG_T_FALL_5, REG_T_FALL_6, REG_T_FALL_7, + 0xFF, 0xFF, 0xFF, 0xFF, + REG_T_FALL_12, REG_T_FALL_13, REG_T_FALL_14, REG_T_FALL_15}; +}; + +} // namespace sx1509 +} // namespace esphome diff --git a/esphome/components/sx1509/sx1509_registers.h b/esphome/components/sx1509/sx1509_registers.h new file mode 100644 index 0000000000..57836fd5ab --- /dev/null +++ b/esphome/components/sx1509/sx1509_registers.h @@ -0,0 +1,138 @@ +/****************************************************************************** +sx1509_registers.h +Register definitions for SX1509. +Jim Lindblom @ SparkFun Electronics +Original Creation Date: September 21, 2015 +https://github.com/sparkfun/SparkFun_SX1509_Arduino_Library + +Here you'll find the Arduino code used to interface with the SX1509 I2C +16 I/O expander. There are functions to take advantage of everything the +SX1509 provides - input/output setting, writing pins high/low, reading +the input value of pins, LED driver utilities (blink, breath, pwm), and +keypad engine utilites. + +Development environment specifics: + IDE: Arduino 1.6.5 + Hardware Platform: Arduino Uno + SX1509 Breakout Version: v2.0 + +This code is beerware; if you see me (or any other SparkFun employee) at the +local, and you've found our code helpful, please buy us a round! + +Distributed as-is; no warranty is given. +******************************************************************************/ + +#define REG_INPUT_DISABLE_B 0x00 // RegInputDisableB Input buffer disable register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_INPUT_DISABLE_A 0x01 // RegInputDisableA Input buffer disable register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_LONG_SLEW_B 0x02 // RegLongSlewB Output buffer long slew register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_LONG_SLEW_A 0x03 // RegLongSlewA Output buffer long slew register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_LOW_DRIVE_B 0x04 // RegLowDriveB Output buffer low drive register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_LOW_DRIVE_A 0x05 // RegLowDriveA Output buffer low drive register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_PULL_UP_B 0x06 // RegPullUpB Pull_up register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_PULL_UP_A 0x07 // RegPullUpA Pull_up register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_PULL_DOWN_B 0x08 // RegPullDownB Pull_down register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_PULL_DOWN_A 0x09 // RegPullDownA Pull_down register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_OPEN_DRAIN_B 0x0A // RegOpenDrainB Open drain register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_OPEN_DRAIN_A 0x0B // RegOpenDrainA Open drain register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_POLARITY_B 0x0C // RegPolarityB Polarity register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_POLARITY_A 0x0D // RegPolarityA Polarity register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_DIR_B 0x0E // RegDirB Direction register _ I/O[15_8] (Bank B) 1111 1111 +#define REG_DIR_A 0x0F // RegDirA Direction register _ I/O[7_0] (Bank A) 1111 1111 +#define REG_DATA_B 0x10 // RegDataB Data register _ I/O[15_8] (Bank B) 1111 1111* +#define REG_DATA_A 0x11 // RegDataA Data register _ I/O[7_0] (Bank A) 1111 1111* +#define REG_INTERRUPT_MASK_B 0x12 // RegInterruptMaskB Interrupt mask register _ I/O[15_8] (Bank B) 1111 1111 +#define REG_INTERRUPT_MASK_A 0x13 // RegInterruptMaskA Interrupt mask register _ I/O[7_0] (Bank A) 1111 1111 +#define REG_SENSE_HIGH_B 0x14 // RegSenseHighB Sense register for I/O[15:12] 0000 0000 +#define REG_SENSE_LOW_B 0x15 // RegSenseLowB Sense register for I/O[11:8] 0000 0000 +#define REG_SENSE_HIGH_A 0x16 // RegSenseHighA Sense register for I/O[7:4] 0000 0000 +#define REG_SENSE_LOW_A 0x17 // RegSenseLowA Sense register for I/O[3:0] 0000 0000 +#define REG_INTERRUPT_SOURCE_B 0x18 // RegInterruptSourceB Interrupt source register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_INTERRUPT_SOURCE_A 0x19 // RegInterruptSourceA Interrupt source register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_EVENT_STATUS_B 0x1A // RegEventStatusB Event status register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_EVENT_STATUS_A 0x1B // RegEventStatusA Event status register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_LEVEL_SHIFTER_1 0x1C // RegLevelShifter1 Level shifter register 0000 0000 +#define REG_LEVEL_SHIFTER_2 0x1D // RegLevelShifter2 Level shifter register 0000 0000 +#define REG_CLOCK 0x1E // RegClock Clock management register 0000 0000 +#define REG_MISC 0x1F // RegMisc Miscellaneous device settings register 0000 0000 +#define REG_LED_DRIVER_ENABLE_B 0x20 // RegLEDDriverEnableB LED driver enable register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_LED_DRIVER_ENABLE_A 0x21 // RegLEDDriverEnableA LED driver enable register _ I/O[7_0] (Bank A) 0000 0000 +// Debounce and Keypad Engine +#define REG_DEBOUNCE_CONFIG 0x22 // RegDebounceConfig Debounce configuration register 0000 0000 +#define REG_DEBOUNCE_ENABLE_B 0x23 // RegDebounceEnableB Debounce enable register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_DEBOUNCE_ENABLE_A 0x24 // RegDebounceEnableA Debounce enable register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_KEY_CONFIG_1 0x25 // RegKeyConfig1 Key scan configuration register 0000 0000 +#define REG_KEY_CONFIG_2 0x26 // RegKeyConfig2 Key scan configuration register 0000 0000 +#define REG_KEY_DATA_1 0x27 // RegKeyData1 Key value (column) 1111 1111 +#define REG_KEY_DATA_2 0x28 // RegKeyData2 Key value (row) 1111 1111 +// LED Driver (PWM, blinking, breathing) +#define REG_T_ON_0 0x29 // RegTOn0 ON time register for I/O[0] 0000 0000 +#define REG_I_ON_0 0x2A // RegIOn0 ON intensity register for I/O[0] 1111 1111 +#define REG_OFF_0 0x2B // RegOff0 OFF time/intensity register for I/O[0] 0000 0000 +#define REG_T_ON_1 0x2C // RegTOn1 ON time register for I/O[1] 0000 0000 +#define REG_I_ON_1 0x2D // RegIOn1 ON intensity register for I/O[1] 1111 1111 +#define REG_OFF_1 0x2E // RegOff1 OFF time/intensity register for I/O[1] 0000 0000 +#define REG_T_ON_2 0x2F // RegTOn2 ON time register for I/O[2] 0000 0000 +#define REG_I_ON_2 0x30 // RegIOn2 ON intensity register for I/O[2] 1111 1111 +#define REG_OFF_2 0x31 // RegOff2 OFF time/intensity register for I/O[2] 0000 0000 +#define REG_T_ON_3 0x32 // RegTOn3 ON time register for I/O[3] 0000 0000 +#define REG_I_ON_3 0x33 // RegIOn3 ON intensity register for I/O[3] 1111 1111 +#define REG_OFF_3 0x34 // RegOff3 OFF time/intensity register for I/O[3] 0000 0000 +#define REG_T_ON_4 0x35 // RegTOn4 ON time register for I/O[4] 0000 0000 +#define REG_I_ON_4 0x36 // RegIOn4 ON intensity register for I/O[4] 1111 1111 +#define REG_OFF_4 0x37 // RegOff4 OFF time/intensity register for I/O[4] 0000 0000 +#define REG_T_RISE_4 0x38 // RegTRise4 Fade in register for I/O[4] 0000 0000 +#define REG_T_FALL_4 0x39 // RegTFall4 Fade out register for I/O[4] 0000 0000 +#define REG_T_ON_5 0x3A // RegTOn5 ON time register for I/O[5] 0000 0000 +#define REG_I_ON_5 0x3B // RegIOn5 ON intensity register for I/O[5] 1111 1111 +#define REG_OFF_5 0x3C // RegOff5 OFF time/intensity register for I/O[5] 0000 0000 +#define REG_T_RISE_5 0x3D // RegTRise5 Fade in register for I/O[5] 0000 0000 +#define REG_T_FALL_5 0x3E // RegTFall5 Fade out register for I/O[5] 0000 0000 +#define REG_T_ON_6 0x3F // RegTOn6 ON time register for I/O[6] 0000 0000 +#define REG_I_ON_6 0x40 // RegIOn6 ON intensity register for I/O[6] 1111 1111 +#define REG_OFF_6 0x41 // RegOff6 OFF time/intensity register for I/O[6] 0000 0000 +#define REG_T_RISE_6 0x42 // RegTRise6 Fade in register for I/O[6] 0000 0000 +#define REG_T_FALL_6 0x43 // RegTFall6 Fade out register for I/O[6] 0000 0000 +#define REG_T_ON_7 0x44 // RegTOn7 ON time register for I/O[7] 0000 0000 +#define REG_I_ON_7 0x45 // RegIOn7 ON intensity register for I/O[7] 1111 1111 +#define REG_OFF_7 0x46 // RegOff7 OFF time/intensity register for I/O[7] 0000 0000 +#define REG_T_RISE_7 0x47 // RegTRise7 Fade in register for I/O[7] 0000 0000 +#define REG_T_FALL_7 0x48 // RegTFall7 Fade out register for I/O[7] 0000 0000 +#define REG_T_ON_8 0x49 // RegTOn8 ON time register for I/O[8] 0000 0000 +#define REG_I_ON_8 0x4A // RegIOn8 ON intensity register for I/O[8] 1111 1111 +#define REG_OFF_8 0x4B // RegOff8 OFF time/intensity register for I/O[8] 0000 0000 +#define REG_T_ON_9 0x4C // RegTOn9 ON time register for I/O[9] 0000 0000 +#define REG_I_ON_9 0x4D // RegIOn9 ON intensity register for I/O[9] 1111 1111 +#define REG_OFF_9 0x4E // RegOff9 OFF time/intensity register for I/O[9] 0000 0000 +#define REG_T_ON_10 0x4F // RegTOn10 ON time register for I/O[10] 0000 0000 +#define REG_I_ON_10 0x50 // RegIOn10 ON intensity register for I/O[10] 1111 1111 +#define REG_OFF_10 0x51 // RegOff10 OFF time/intensity register for I/O[10] 0000 0000 +#define REG_T_ON_11 0x52 // RegTOn11 ON time register for I/O[11] 0000 0000 +#define REG_I_ON_11 0x53 // RegIOn11 ON intensity register for I/O[11] 1111 1111 +#define REG_OFF_11 0x54 // RegOff11 OFF time/intensity register for I/O[11] 0000 0000 +#define REG_T_ON_12 0x55 // RegTOn12 ON time register for I/O[12] 0000 0000 +#define REG_I_ON_12 0x56 // RegIOn12 ON intensity register for I/O[12] 1111 1111 +#define REG_OFF_12 0x57 // RegOff12 OFF time/intensity register for I/O[12] 0000 0000 +#define REG_T_RISE_12 0x58 // RegTRise12 Fade in register for I/O[12] 0000 0000 +#define REG_T_FALL_12 0x59 // RegTFall12 Fade out register for I/O[12] 0000 0000 +#define REG_T_ON_13 0x5A // RegTOn13 ON time register for I/O[13] 0000 0000 +#define REG_I_ON_13 0x5B // RegIOn13 ON intensity register for I/O[13] 1111 1111 +#define REG_OFF_13 0x5C // RegOff13 OFF time/intensity register for I/O[13] 0000 0000 +#define REG_T_RISE_13 0x5D // RegTRise13 Fade in register for I/O[13] 0000 0000 +#define REG_T_FALL_13 0x5E // RegTFall13 Fade out register for I/O[13] 0000 0000 +#define REG_T_ON_14 0x5F // RegTOn14 ON time register for I/O[14] 0000 0000 +#define REG_I_ON_14 0x60 // RegIOn14 ON intensity register for I/O[14] 1111 1111 +#define REG_OFF_14 0x61 // RegOff14 OFF time/intensity register for I/O[14] 0000 0000 +#define REG_T_RISE_14 0x62 // RegTRise14 Fade in register for I/O[14] 0000 0000 +#define REG_T_FALL_14 0x63 // RegTFall14 Fade out register for I/O[14] 0000 0000 +#define REG_T_ON_15 0x64 // RegTOn15 ON time register for I/O[15] 0000 0000 +#define REG_I_ON_15 0x65 // RegIOn15 ON intensity register for I/O[15] 1111 1111 +#define REG_OFF_15 0x66 // RegOff15 OFF time/intensity register for I/O[15] 0000 0000 +#define REG_T_RISE_15 0x67 // RegTRise15 Fade in register for I/O[15] 0000 0000 +#define REG_T_FALL_15 0x68 // RegTFall15 Fade out register for I/O[15] 0000 0000 +// Miscellaneous +#define REG_HIGH_INPUT_B 0x69 // RegHighInputB High input enable register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_HIGH_INPUT_A 0x6A // RegHighInputA High input enable register _ I/O[7_0] (Bank A) 0000 0000 +// Software Reset +#define REG_RESET 0x7D // RegReset Software reset register 0000 0000 +#define REG_TEST_1 0x7E // RegTest1 Test register 0000 0000 +#define REG_TEST_2 0x7F // RegTest2 Test register 0000 0000