352 lines
10 KiB
C++
352 lines
10 KiB
C++
/*!
|
|
* @file Adafruit_seesaw.h
|
|
*
|
|
* This is part of Adafruit's seesaw driver for the Arduino platform. It is
|
|
* designed specifically to work with the Adafruit products that use seesaw
|
|
* technology.
|
|
*
|
|
* These chips use I2C to communicate, 2 pins (SCL+SDA) are required
|
|
* to interface with the board.
|
|
*
|
|
* Adafruit invests time and resources providing this open source code,
|
|
* please support Adafruit and open-source hardware by purchasing
|
|
* products from Adafruit!
|
|
*
|
|
* Written by Dean Miller for Adafruit Industries.
|
|
*
|
|
* BSD license, all text here must be included in any redistribution.
|
|
*
|
|
*/
|
|
|
|
#ifndef LIB_SEESAW_H
|
|
#define LIB_SEESAW_H
|
|
|
|
#include "Adafruit_I2CDevice.h"
|
|
#include <Arduino.h>
|
|
#include <Wire.h>
|
|
|
|
/*=========================================================================
|
|
I2C ADDRESS/BITS
|
|
-----------------------------------------------------------------------*/
|
|
#define SEESAW_ADDRESS (0x49) ///< Default Seesaw I2C address
|
|
/*=========================================================================*/
|
|
|
|
/*=========================================================================
|
|
REGISTERS
|
|
-----------------------------------------------------------------------*/
|
|
|
|
/** Module Base Addreses
|
|
* The module base addresses for different seesaw modules.
|
|
*/
|
|
enum {
|
|
SEESAW_STATUS_BASE = 0x00,
|
|
SEESAW_GPIO_BASE = 0x01,
|
|
SEESAW_SERCOM0_BASE = 0x02,
|
|
|
|
SEESAW_TIMER_BASE = 0x08,
|
|
SEESAW_ADC_BASE = 0x09,
|
|
SEESAW_DAC_BASE = 0x0A,
|
|
SEESAW_INTERRUPT_BASE = 0x0B,
|
|
SEESAW_DAP_BASE = 0x0C,
|
|
SEESAW_EEPROM_BASE = 0x0D,
|
|
SEESAW_NEOPIXEL_BASE = 0x0E,
|
|
SEESAW_TOUCH_BASE = 0x0F,
|
|
SEESAW_KEYPAD_BASE = 0x10,
|
|
SEESAW_ENCODER_BASE = 0x11,
|
|
SEESAW_SPECTRUM_BASE = 0x12,
|
|
SEESAW_SOIL_BASE = 0x13,
|
|
};
|
|
|
|
/** GPIO module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_GPIO_DIRSET_BULK = 0x02,
|
|
SEESAW_GPIO_DIRCLR_BULK = 0x03,
|
|
SEESAW_GPIO_BULK = 0x04,
|
|
SEESAW_GPIO_BULK_SET = 0x05,
|
|
SEESAW_GPIO_BULK_CLR = 0x06,
|
|
SEESAW_GPIO_BULK_TOGGLE = 0x07,
|
|
SEESAW_GPIO_INTENSET = 0x08,
|
|
SEESAW_GPIO_INTENCLR = 0x09,
|
|
SEESAW_GPIO_INTFLAG = 0x0A,
|
|
SEESAW_GPIO_PULLENSET = 0x0B,
|
|
SEESAW_GPIO_PULLENCLR = 0x0C,
|
|
};
|
|
|
|
/** status module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_STATUS_HW_ID = 0x01,
|
|
SEESAW_STATUS_VERSION = 0x02,
|
|
SEESAW_STATUS_OPTIONS = 0x03,
|
|
SEESAW_STATUS_TEMP = 0x04,
|
|
SEESAW_STATUS_SWRST = 0x7F,
|
|
};
|
|
|
|
/** timer module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_TIMER_STATUS = 0x00,
|
|
SEESAW_TIMER_PWM = 0x01,
|
|
SEESAW_TIMER_FREQ = 0x02,
|
|
};
|
|
|
|
/** ADC module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_ADC_STATUS = 0x00,
|
|
SEESAW_ADC_INTEN = 0x02,
|
|
SEESAW_ADC_INTENCLR = 0x03,
|
|
SEESAW_ADC_WINMODE = 0x04,
|
|
SEESAW_ADC_WINTHRESH = 0x05,
|
|
SEESAW_ADC_CHANNEL_OFFSET = 0x07,
|
|
};
|
|
|
|
/** Sercom module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_SERCOM_STATUS = 0x00,
|
|
SEESAW_SERCOM_INTEN = 0x02,
|
|
SEESAW_SERCOM_INTENCLR = 0x03,
|
|
SEESAW_SERCOM_BAUD = 0x04,
|
|
SEESAW_SERCOM_DATA = 0x05,
|
|
};
|
|
|
|
/** neopixel module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_NEOPIXEL_STATUS = 0x00,
|
|
SEESAW_NEOPIXEL_PIN = 0x01,
|
|
SEESAW_NEOPIXEL_SPEED = 0x02,
|
|
SEESAW_NEOPIXEL_BUF_LENGTH = 0x03,
|
|
SEESAW_NEOPIXEL_BUF = 0x04,
|
|
SEESAW_NEOPIXEL_SHOW = 0x05,
|
|
};
|
|
|
|
/** touch module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_TOUCH_CHANNEL_OFFSET = 0x10,
|
|
};
|
|
|
|
/** keypad module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_KEYPAD_STATUS = 0x00,
|
|
SEESAW_KEYPAD_EVENT = 0x01,
|
|
SEESAW_KEYPAD_INTENSET = 0x02,
|
|
SEESAW_KEYPAD_INTENCLR = 0x03,
|
|
SEESAW_KEYPAD_COUNT = 0x04,
|
|
SEESAW_KEYPAD_FIFO = 0x10,
|
|
};
|
|
|
|
/** keypad module edge definitions
|
|
*/
|
|
enum {
|
|
SEESAW_KEYPAD_EDGE_HIGH = 0,
|
|
SEESAW_KEYPAD_EDGE_LOW,
|
|
SEESAW_KEYPAD_EDGE_FALLING,
|
|
SEESAW_KEYPAD_EDGE_RISING,
|
|
};
|
|
|
|
/** encoder module edge definitions
|
|
*/
|
|
enum {
|
|
SEESAW_ENCODER_STATUS = 0x00,
|
|
SEESAW_ENCODER_INTENSET = 0x10,
|
|
SEESAW_ENCODER_INTENCLR = 0x20,
|
|
SEESAW_ENCODER_POSITION = 0x30,
|
|
SEESAW_ENCODER_DELTA = 0x40,
|
|
};
|
|
|
|
/** Audio spectrum module function address registers
|
|
*/
|
|
enum {
|
|
SEESAW_SPECTRUM_RESULTS_LOWER = 0x00, // Audio spectrum bins 0-31
|
|
SEESAW_SPECTRUM_RESULTS_UPPER = 0x01, // Audio spectrum bins 32-63
|
|
// If some future device supports a larger spectrum, can add additional
|
|
// "bins" working upward from here. Configurable setting registers then
|
|
// work downward from the top to avoid collision between spectrum bins
|
|
// and configurables.
|
|
SEESAW_SPECTRUM_CHANNEL = 0xFD,
|
|
SEESAW_SPECTRUM_RATE = 0xFE,
|
|
SEESAW_SPECTRUM_STATUS = 0xFF,
|
|
};
|
|
|
|
/** soil moisture module function address registers
|
|
*/
|
|
enum {
|
|
// 0x00..0x0F Global Settings
|
|
SEESAW_SOIL_STATUS = 0x00,
|
|
SEESAW_SOIL_RATE = 0x01,
|
|
// 0x10..0xF0 Sensor Settings
|
|
// lower four bits = sensor number
|
|
// upper four bits = setting type
|
|
SEESAW_SOIL_VALUE = 0x10,
|
|
SEESAW_SOIL_SAMPLES = 0x20,
|
|
SEESAW_SOIL_XDELAY = 0x30,
|
|
SEESAW_SOIL_TIMEOUT = 0x40,
|
|
};
|
|
|
|
#define ADC_INPUT_0_PIN 2 ///< default ADC input pin
|
|
#define ADC_INPUT_1_PIN 3 ///< default ADC input pin
|
|
#define ADC_INPUT_2_PIN 4 ///< default ADC input pin
|
|
#define ADC_INPUT_3_PIN 5 ///< default ADC input pin
|
|
|
|
#define PWM_0_PIN 4 ///< default PWM output pin
|
|
#define PWM_1_PIN 5 ///< default PWM output pin
|
|
#define PWM_2_PIN 6 ///< default PWM output pin
|
|
#define PWM_3_PIN 7 ///< default PWM output pin
|
|
|
|
#ifndef INPUT_PULLDOWN
|
|
#define INPUT_PULLDOWN \
|
|
0x03 ///< for compatibility with platforms that do not already define
|
|
///< INPUT_PULLDOWN
|
|
#endif
|
|
|
|
/*=========================================================================*/
|
|
// clang-format off
|
|
#define SEESAW_HW_ID_CODE_SAMD09 0x55 ///< seesaw HW ID code for SAMD09
|
|
#define SEESAW_HW_ID_CODE_TINY806 0x84 ///< seesaw HW ID code for ATtiny806
|
|
#define SEESAW_HW_ID_CODE_TINY807 0x85 ///< seesaw HW ID code for ATtiny807
|
|
#define SEESAW_HW_ID_CODE_TINY816 0x86 ///< seesaw HW ID code for ATtiny816
|
|
#define SEESAW_HW_ID_CODE_TINY817 0x87 ///< seesaw HW ID code for ATtiny817
|
|
#define SEESAW_HW_ID_CODE_TINY1616 0x88 ///< seesaw HW ID code for ATtiny1616
|
|
#define SEESAW_HW_ID_CODE_TINY1617 0x89 ///< seesaw HW ID code for ATtiny1617
|
|
// clang-format on
|
|
|
|
/** raw key event stucture for keypad module */
|
|
union keyEventRaw {
|
|
struct {
|
|
uint8_t EDGE : 2; ///< the edge that was triggered
|
|
uint8_t NUM : 6; ///< the event number
|
|
} bit; ///< bitfield format
|
|
uint8_t reg; ///< register format
|
|
};
|
|
|
|
/** extended key event stucture for keypad module */
|
|
union keyEvent {
|
|
struct {
|
|
uint8_t EDGE : 2; ///< the edge that was triggered
|
|
uint16_t NUM : 14; ///< the event number
|
|
} bit; ///< bitfield format
|
|
uint16_t reg; ///< register format
|
|
};
|
|
|
|
/** key state struct that will be written to seesaw chip keypad module */
|
|
union keyState {
|
|
struct {
|
|
uint8_t STATE : 1; ///< the current state of the key
|
|
uint8_t ACTIVE : 4; ///< the registered events for that key
|
|
} bit; ///< bitfield format
|
|
uint8_t reg; ///< register format
|
|
};
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Class that stores state and functions for interacting with seesaw
|
|
helper IC
|
|
*/
|
|
/**************************************************************************/
|
|
class Adafruit_seesaw : public Print {
|
|
public:
|
|
// constructors
|
|
Adafruit_seesaw(TwoWire *Wi = NULL);
|
|
~Adafruit_seesaw(void){};
|
|
|
|
bool begin(uint8_t addr = SEESAW_ADDRESS, int8_t flow = -1,
|
|
bool reset = true);
|
|
uint32_t getOptions();
|
|
uint32_t getVersion();
|
|
bool getProdDatecode(uint16_t *pid, uint8_t *year, uint8_t *mon,
|
|
uint8_t *day);
|
|
|
|
bool SWReset();
|
|
|
|
void pinMode(uint8_t pin, uint8_t mode);
|
|
void pinModeBulk(uint32_t pins, uint8_t mode);
|
|
void pinModeBulk(uint32_t pinsa, uint32_t pinsb, uint8_t mode);
|
|
virtual void analogWrite(uint8_t pin, uint16_t value, uint8_t width = 8);
|
|
void digitalWrite(uint8_t pin, uint8_t value);
|
|
void digitalWriteBulk(uint32_t port_values);
|
|
void digitalWriteBulk(uint32_t pins, uint8_t value);
|
|
void digitalWriteBulk(uint32_t pinsa, uint32_t pinsb, uint8_t value);
|
|
|
|
bool digitalRead(uint8_t pin);
|
|
uint32_t digitalReadBulk(uint32_t pins);
|
|
uint32_t digitalReadBulkB(uint32_t pins);
|
|
|
|
void setGPIOInterrupts(uint32_t pins, bool enabled);
|
|
|
|
virtual uint16_t analogRead(uint8_t pin);
|
|
|
|
uint16_t touchRead(uint8_t pin);
|
|
|
|
virtual void setPWMFreq(uint8_t pin, uint16_t freq);
|
|
|
|
void enableSercomDataRdyInterrupt(uint8_t sercom = 0);
|
|
void disableSercomDataRdyInterrupt(uint8_t sercom = 0);
|
|
|
|
char readSercomData(uint8_t sercom = 0);
|
|
|
|
void EEPROMWrite8(uint8_t addr, uint8_t val);
|
|
void EEPROMWrite(uint8_t addr, uint8_t *buf, uint8_t size);
|
|
uint8_t EEPROMRead8(uint8_t addr);
|
|
|
|
void setI2CAddr(uint8_t addr);
|
|
uint8_t getI2CAddr();
|
|
|
|
void UARTSetBaud(uint32_t baud);
|
|
|
|
void setKeypadEvent(uint8_t key, uint8_t edge, bool enable = true);
|
|
void enableKeypadInterrupt();
|
|
void disableKeypadInterrupt();
|
|
uint8_t getKeypadCount();
|
|
bool readKeypad(keyEventRaw *buf, uint8_t count);
|
|
|
|
float getTemp();
|
|
|
|
int32_t getEncoderPosition(uint8_t encoder = 0);
|
|
int32_t getEncoderDelta(uint8_t encoder = 0);
|
|
bool enableEncoderInterrupt(uint8_t encoder = 0);
|
|
bool disableEncoderInterrupt(uint8_t encoder = 0);
|
|
void setEncoderPosition(int32_t pos, uint8_t encoder = 0);
|
|
|
|
virtual size_t write(uint8_t);
|
|
virtual size_t write(const char *str);
|
|
|
|
protected:
|
|
TwoWire *_i2cbus; /*!< The I2C Bus used to communicate with the seesaw */
|
|
Adafruit_I2CDevice *_i2c_dev = NULL; ///< The BusIO device for I2C control
|
|
|
|
int8_t _flow; /*!< The flow control pin to use */
|
|
|
|
uint8_t _hardwaretype = 0; /*!< what hardware type is attached! */
|
|
uint8_t getI2CaddrEEPROMloc();
|
|
|
|
bool write8(byte regHigh, byte regLow, byte value);
|
|
uint8_t read8(byte regHigh, byte regLow, uint16_t delay = 250);
|
|
|
|
bool read(uint8_t regHigh, uint8_t regLow, uint8_t *buf, uint8_t num,
|
|
uint16_t delay = 250);
|
|
bool write(uint8_t regHigh, uint8_t regLow, uint8_t *buf, uint8_t num);
|
|
|
|
/*=========================================================================
|
|
REGISTER BITFIELDS
|
|
-----------------------------------------------------------------------*/
|
|
|
|
/** Sercom interrupt enable register
|
|
*/
|
|
union sercom_inten {
|
|
struct {
|
|
uint8_t DATA_RDY : 1; ///< this bit is set when data becomes available
|
|
} bit; ///< bitfields
|
|
uint8_t reg; ///< full register
|
|
};
|
|
sercom_inten _sercom_inten; ///< sercom interrupt enable register instance
|
|
|
|
/*=========================================================================*/
|
|
};
|
|
|
|
#endif
|