初始化提交

This commit is contained in:
王立帮
2024-07-20 22:09:06 +08:00
commit c247dd07a6
6876 changed files with 2743096 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
#include "Adafruit_Crickit.h"
// the pwm pins
#define CRICKIT_NUM_PWM 12
static const uint8_t CRICKIT_pwms[CRICKIT_NUM_PWM] = {
CRICKIT_SERVO4, CRICKIT_SERVO3, CRICKIT_SERVO2, CRICKIT_SERVO1,
CRICKIT_MOTOR_B1, CRICKIT_MOTOR_B2, CRICKIT_MOTOR_A1, CRICKIT_MOTOR_A2,
CRICKIT_DRIVE4, CRICKIT_DRIVE3, CRICKIT_DRIVE2, CRICKIT_DRIVE1};
// the adc pin
#define CRICKIT_NUM_ADC 8
static const uint8_t CRICKIT_adc[CRICKIT_NUM_ADC] = {
CRICKIT_SIGNAL1, CRICKIT_SIGNAL2, CRICKIT_SIGNAL3, CRICKIT_SIGNAL4,
CRICKIT_SIGNAL5, CRICKIT_SIGNAL6, CRICKIT_SIGNAL7, CRICKIT_SIGNAL8};
void Adafruit_Crickit::analogWrite(uint8_t pin, uint16_t value, uint8_t width) {
(void)width;
int8_t p = -1;
for (int i = 0; i < CRICKIT_NUM_PWM; i++) {
if (CRICKIT_pwms[i] == pin) {
p = i;
break;
}
}
if (p > -1) {
uint8_t cmd[] = {(uint8_t)p, (uint8_t)(value >> 8), (uint8_t)value};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_PWM, cmd, 3);
}
}
uint16_t Adafruit_Crickit::analogRead(uint8_t pin) {
uint8_t buf[2];
int8_t p = -1;
for (int i = 0; i < CRICKIT_NUM_ADC; i++) {
if (CRICKIT_adc[i] == pin) {
p = i;
break;
}
}
if (p > -1) {
this->read(SEESAW_ADC_BASE, SEESAW_ADC_CHANNEL_OFFSET + p, buf, 2, 500);
uint16_t ret = ((uint16_t)buf[0] << 8) | buf[1];
delay(1);
return ret;
} else
return 0;
}
void Adafruit_Crickit::setPWMFreq(uint8_t pin, uint16_t freq) {
int8_t p = -1;
for (int i = 0; i < CRICKIT_NUM_PWM; i++) {
if (CRICKIT_pwms[i] == pin) {
p = i;
break;
}
}
if (p > -1) {
uint8_t cmd[] = {(uint8_t)p, (uint8_t)(freq >> 8), (uint8_t)freq};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_FREQ, cmd, 3);
}
}

View File

@@ -0,0 +1,53 @@
#ifndef _CRICKIT_TERSTER_H
#define _CRICKIT_TERSTER_H
#include "Adafruit_seesaw.h"
#define CRICKIT_SIGNAL1 2
#define CRICKIT_SIGNAL2 3
#define CRICKIT_SIGNAL3 40
#define CRICKIT_SIGNAL4 41
#define CRICKIT_SIGNAL5 11
#define CRICKIT_SIGNAL6 10
#define CRICKIT_SIGNAL7 9
#define CRICKIT_SIGNAL8 8
#define CRICKIT_SERVO4 14
#define CRICKIT_SERVO3 15
#define CRICKIT_SERVO2 16
#define CRICKIT_SERVO1 17
#define CRICKIT_MOTOR_A1 22
#define CRICKIT_MOTOR_A2 23
#define CRICKIT_MOTOR_B1 19
#define CRICKIT_MOTOR_B2 18
#define CRICKIT_DRIVE1 13
#define CRICKIT_DRIVE2 12
#define CRICKIT_DRIVE3 43
#define CRICKIT_DRIVE4 42
#define CRICKIT_TOUCH1 0
#define CRICKIT_TOUCH2 1
#define CRICKIT_TOUCH3 2
#define CRICKIT_TOUCH4 3
#define CRICKIT_DUTY_CYCLE_OFF 0
#define CRICKIT_DUTY_CYCLE_MAX 65535
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with Crickit
variant of seesaw helper IC
*/
/**************************************************************************/
class Adafruit_Crickit : public Adafruit_seesaw {
public:
Adafruit_Crickit(){};
~Adafruit_Crickit(){};
void analogWrite(uint8_t pin, uint16_t value, uint8_t width = 8);
uint16_t analogRead(uint8_t pin);
void setPWMFreq(uint8_t pin, uint16_t freq);
};
#endif

View File

@@ -0,0 +1,351 @@
#include "Adafruit_NeoTrellis.h"
/**************************************************************************/
/*!
@brief Class constructor
@param addr the I2C address this neotrellis object uses
*/
/**************************************************************************/
Adafruit_NeoTrellis::Adafruit_NeoTrellis(uint8_t addr)
: pixels(NEO_TRELLIS_NUM_KEYS, NEO_TRELLIS_NEOPIX_PIN,
NEO_GRB + NEO_KHZ800) {
for (int i = 0; i < NEO_TRELLIS_NUM_KEYS; i++) {
_callbacks[i] = NULL;
}
this->_addr = addr;
}
/**************************************************************************/
/*!
@brief Begin communication with the RGB trellis.
@param addr optional i2c address where the device can be found. Defaults to
NEO_TRELLIS_ADDR
@param flow optional flow control pin
@returns true on success, false on error.
*/
/**************************************************************************/
bool Adafruit_NeoTrellis::begin(uint8_t addr, int8_t flow) {
_addr = addr;
bool ret = pixels.begin(addr, flow);
ret = Adafruit_seesaw::begin(addr, flow, false);
if (!ret)
return ret;
enableKeypadInterrupt();
return ret;
}
/**************************************************************************/
/*!
@brief register a callback function on the passed key.
@param key the key number to register the callback on
@param cb the callback function that should be called when an event on that
key happens
*/
/**************************************************************************/
void Adafruit_NeoTrellis::registerCallback(uint8_t key,
TrellisCallback (*cb)(keyEvent)) {
_callbacks[key] = cb;
}
/**************************************************************************/
/*!
@brief unregister a callback on a given key
@param key the key number the callback is currently mapped to.
*/
/**************************************************************************/
void Adafruit_NeoTrellis::unregisterCallback(uint8_t key) {
_callbacks[key] = NULL;
}
/**************************************************************************/
/*!
@brief activate or deactivate a given key event
@param key the key number to map the event to
@param edge the edge sensitivity of the event
@param enable pass true to enable the passed event, false to disable it.
*/
/**************************************************************************/
void Adafruit_NeoTrellis::activateKey(uint8_t key, uint8_t edge, bool enable) {
setKeypadEvent(NEO_TRELLIS_KEY(key), edge, enable);
}
/**************************************************************************/
/*!
@brief read all events currently stored in the seesaw fifo and call any
callbacks.
@param polling pass true if the interrupt pin is not being used, false if
it is. Defaults to true.
*/
/**************************************************************************/
void Adafruit_NeoTrellis::read(bool polling) {
uint8_t count = getKeypadCount();
delayMicroseconds(500);
if (count > 0) {
if (polling)
count = count + 2;
keyEventRaw e[count];
readKeypad(e, count);
for (int i = 0; i < count; i++) {
// call any callbacks associated with the key
e[i].bit.NUM = NEO_TRELLIS_SEESAW_KEY(e[i].bit.NUM);
if (e[i].bit.NUM < NEO_TRELLIS_NUM_KEYS &&
_callbacks[e[i].bit.NUM] != NULL) {
keyEvent evt = {e[i].bit.EDGE, e[i].bit.NUM};
_callbacks[e[i].bit.NUM](evt);
}
}
}
}
/**************************************************************************/
/*!
@brief class constructor
@param trelli pointer to a multidimensional array of neotrellis objects.
these object must have their I2C addresses specified in the class
constructors.
@param rows the number of individual neotrellis boards in the Y direction
of your matrix.
@param cols the number of individual neotrellis boards in the X direction
of your matrix.
*/
/**************************************************************************/
Adafruit_MultiTrellis::Adafruit_MultiTrellis(Adafruit_NeoTrellis *trelli,
uint8_t rows, uint8_t cols) {
this->_rows = rows;
this->_cols = cols;
this->_trelli = trelli;
}
/**************************************************************************/
/*!
@brief begin communication with the matrix of neotrellis boards.
@returns true on success, false otherwise.
*/
/**************************************************************************/
bool Adafruit_MultiTrellis::begin() {
Adafruit_NeoTrellis *t;
for (int n = 0; n < _rows; n++) {
for (int m = 0; m < _cols; m++) {
t = (_trelli + n * _cols) + m;
if (!t->begin(t->_addr))
return false;
}
}
return true;
}
/**************************************************************************/
/*!
@brief register a callback for a key addressed by key index.
@param x the column index of the key. column 0 is on the lefthand side of
the matix.
@param y the row index of the key. row 0 is at the top of the matrix and
the numbers increase downwards.
@param cb the function to be called when an event from the specified key is
detected.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::registerCallback(uint8_t x, uint8_t y,
TrellisCallback (*cb)(keyEvent)) {
Adafruit_NeoTrellis *t =
(_trelli + y / NEO_TRELLIS_NUM_ROWS * _cols) + x / NEO_TRELLIS_NUM_COLS;
int xkey = NEO_TRELLIS_X(x);
int ykey = NEO_TRELLIS_Y(y % NEO_TRELLIS_NUM_ROWS * NEO_TRELLIS_NUM_COLS);
t->registerCallback(NEO_TRELLIS_XY(xkey, ykey), cb);
}
/**************************************************************************/
/*!
@brief register a callback for a key addressed by key number.
@param num the keynumber to set the color of. Key 0 is in the top left
corner of the trellis matrix, key 1 is directly to the right of it,
and the last key number is in the bottom righthand corner.
@param cb the function to be called when an event from the specified key is
detected.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::registerCallback(uint16_t num,
TrellisCallback (*cb)(keyEvent)) {
uint8_t x = num % (NEO_TRELLIS_NUM_COLS * _cols);
uint8_t y = num / (NEO_TRELLIS_NUM_COLS * _cols);
registerCallback(x, y, cb);
}
/**************************************************************************/
/*!
@brief Unregister a callback for a key addressed by key index.
@param x the column index of the key. column 0 is on the lefthand side of
the matix.
@param y the row index of the key. row 0 is at the top of the matrix and
the numbers increase downwards.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::unregisterCallback(uint8_t x, uint8_t y) {
Adafruit_NeoTrellis *t =
(_trelli + y / NEO_TRELLIS_NUM_ROWS * _cols) + x / NEO_TRELLIS_NUM_COLS;
int xkey = NEO_TRELLIS_X(x);
int ykey = NEO_TRELLIS_Y(y % NEO_TRELLIS_NUM_ROWS * NEO_TRELLIS_NUM_COLS);
t->unregisterCallback(NEO_TRELLIS_XY(xkey, ykey));
}
/**************************************************************************/
/*!
@brief Unregister a callback for a key addressed by key number.
@param num the keynumber to set the color of. Key 0 is in the top left
corner of the trellis matrix, key 1 is directly to the right of it,
and the last key number is in the bottom righthand corner.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::unregisterCallback(uint16_t num) {
uint8_t x = num % (NEO_TRELLIS_NUM_COLS * _cols);
uint8_t y = num / (NEO_TRELLIS_NUM_COLS * _cols);
unregisterCallback(x, y);
}
/**************************************************************************/
/*!
@brief Activate or deactivate a key by number.
@param x the column index of the key. column 0 is on the lefthand side of
the matix.
@param y the row index of the key. row 0 is at the top of the matrix and
the numbers increase downwards.
@param edge the edge that the key triggers an event on. Use
SEESAW_KEYPAD_EDGE_FALLING or SEESAW_KEYPAD_EDGE_RISING.
@param enable pass true to enable the key on the passed edge, false to
disable.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::activateKey(uint8_t x, uint8_t y, uint8_t edge,
bool enable) {
Adafruit_NeoTrellis *t =
(_trelli + y / NEO_TRELLIS_NUM_ROWS * _cols) + x / NEO_TRELLIS_NUM_COLS;
int xkey = NEO_TRELLIS_X(x);
int ykey = NEO_TRELLIS_Y(y % NEO_TRELLIS_NUM_ROWS * NEO_TRELLIS_NUM_COLS);
t->activateKey(NEO_TRELLIS_XY(xkey, ykey), edge, enable);
}
/**************************************************************************/
/*!
@brief Activate or deactivate a key by number.
@param num the keynumber to set the color of. Key 0 is in the top left
corner of the trellis matrix, key 1 is directly to the right of it,
and the last key number is in the bottom righthand corner.
@param edge the edge that the key triggers an event on. Use
SEESAW_KEYPAD_EDGE_FALLING or SEESAW_KEYPAD_EDGE_RISING.
@param enable pass true to enable the key on the passed edge, false to
disable.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::activateKey(uint16_t num, uint8_t edge,
bool enable) {
uint8_t x = num % (NEO_TRELLIS_NUM_COLS * _cols);
uint8_t y = num / (NEO_TRELLIS_NUM_COLS * _cols);
activateKey(x, y, edge, enable);
}
/**************************************************************************/
/*!
@brief set the color of a neopixel at a key index.
@param x the column index of the key. column 0 is on the lefthand side of
the matix.
@param y the row index of the key. row 0 is at the top of the matrix and
the numbers increase downwards.
@param color the color to set the pixel to. This is a 24 bit RGB value.
for example, full brightness red would be 0xFF0000, and full
brightness blue would be 0x0000FF.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::setPixelColor(uint8_t x, uint8_t y,
uint32_t color) {
Adafruit_NeoTrellis *t =
(_trelli + y / NEO_TRELLIS_NUM_ROWS * _cols) + x / NEO_TRELLIS_NUM_COLS;
int xkey = NEO_TRELLIS_X(x);
int ykey = NEO_TRELLIS_Y(y % NEO_TRELLIS_NUM_ROWS * NEO_TRELLIS_NUM_COLS);
t->pixels.setPixelColor(NEO_TRELLIS_XY(xkey, ykey), color);
}
/**************************************************************************/
/*!
@brief set the color of a neopixel at a key number.
@param num the keynumber to set the color of. Key 0 is in the top left
corner of the trellis matrix, key 1 is directly to the right of it,
and the last key number is in the bottom righthand corner.
@param color the color to set the pixel to. This is a 24 bit RGB value.
for example, full brightness red would be 0xFF0000, and full
brightness blue would be 0x0000FF.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::setPixelColor(uint16_t num, uint32_t color) {
uint8_t x = num % (NEO_TRELLIS_NUM_COLS * _cols);
uint8_t y = num / (NEO_TRELLIS_NUM_COLS * _cols);
setPixelColor(x, y, color);
}
/**************************************************************************/
/*!
@brief call show for all connected neotrellis boards to show all neopixels
*/
/**************************************************************************/
void Adafruit_MultiTrellis::show() {
Adafruit_NeoTrellis *t;
for (int n = 0; n < _rows; n++) {
for (int m = 0; m < _cols; m++) {
t = (_trelli + n * _cols) + m;
t->pixels.show();
}
}
}
/**************************************************************************/
/*!
@brief read all events currently stored in the seesaw fifo and call any
callbacks.
*/
/**************************************************************************/
void Adafruit_MultiTrellis::read() {
Adafruit_NeoTrellis *t;
for (int n = 0; n < _rows; n++) {
for (int m = 0; m < _cols; m++) {
t = (_trelli + n * _cols) + m;
uint8_t count = t->getKeypadCount();
delayMicroseconds(500);
if (count > 0) {
count = count + 2;
keyEventRaw e[count];
t->readKeypad(e, count);
for (int i = 0; i < count; i++) {
// call any callbacks associated with the key
e[i].bit.NUM = NEO_TRELLIS_SEESAW_KEY(e[i].bit.NUM);
if (e[i].bit.NUM < NEO_TRELLIS_NUM_KEYS &&
t->_callbacks[e[i].bit.NUM] != NULL) {
// update the event with the multitrellis number
keyEvent evt = {e[i].bit.EDGE, e[i].bit.NUM};
int x = NEO_TRELLIS_X(e[i].bit.NUM);
int y = NEO_TRELLIS_Y(e[i].bit.NUM);
x = x + m * NEO_TRELLIS_NUM_COLS;
y = y + n * NEO_TRELLIS_NUM_ROWS;
evt.bit.NUM = y * NEO_TRELLIS_NUM_COLS * _cols + x;
t->_callbacks[e[i].bit.NUM](evt);
}
}
}
}
}
}

View File

@@ -0,0 +1,94 @@
#ifndef _NEO_TRELLIS_H
#define _NEO_TRELLIS_H
#include "Adafruit_seesaw.h"
#include "seesaw_neopixel.h"
#include <Arduino.h>
#define NEO_TRELLIS_ADDR 0x2E
#define NEO_TRELLIS_NEOPIX_PIN 3
#define NEO_TRELLIS_NUM_ROWS 4
#define NEO_TRELLIS_NUM_COLS 4
#define NEO_TRELLIS_NUM_KEYS (NEO_TRELLIS_NUM_ROWS * NEO_TRELLIS_NUM_COLS)
#define NEO_TRELLIS_MAX_CALLBACKS 32
#define NEO_TRELLIS_KEY(x) (((x) / 4) * 8 + ((x) % 4))
#define NEO_TRELLIS_SEESAW_KEY(x) (((x) / 8) * 4 + ((x) % 8))
#define NEO_TRELLIS_X(k) ((k) % 4)
#define NEO_TRELLIS_Y(k) ((k) / 4)
#define NEO_TRELLIS_XY(x, y) ((y)*NEO_TRELLIS_NUM_ROWS + (x))
typedef void (*TrellisCallback)(keyEvent evt);
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with the
seesaw keypad module
*/
/**************************************************************************/
class Adafruit_NeoTrellis : public Adafruit_seesaw {
public:
Adafruit_NeoTrellis(uint8_t addr = NEO_TRELLIS_ADDR);
~Adafruit_NeoTrellis(){};
bool begin(uint8_t addr = NEO_TRELLIS_ADDR, int8_t flow = -1);
void registerCallback(uint8_t key, TrellisCallback (*cb)(keyEvent));
void unregisterCallback(uint8_t key);
void activateKey(uint8_t key, uint8_t edge, bool enable = true);
void read(bool polling = true);
seesaw_NeoPixel pixels; ///< the onboard neopixel matrix
friend class Adafruit_MultiTrellis; ///< for allowing use of protected methods
///< by aggregate class
protected:
uint8_t _addr; ///< the I2C address of this board
TrellisCallback (*_callbacks[NEO_TRELLIS_NUM_KEYS])(
keyEvent); ///< the array of callback functions
};
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with multiple
neotrellis boards
*/
/**************************************************************************/
class Adafruit_MultiTrellis {
public:
Adafruit_MultiTrellis(Adafruit_NeoTrellis *trelli, uint8_t rows,
uint8_t cols);
~Adafruit_MultiTrellis(){};
bool begin();
void registerCallback(uint16_t num, TrellisCallback (*cb)(keyEvent));
void registerCallback(uint8_t x, uint8_t y, TrellisCallback (*cb)(keyEvent));
void unregisterCallback(uint16_t num);
void unregisterCallback(uint8_t x, uint8_t y);
void activateKey(uint16_t num, uint8_t edge, bool enable = true);
void activateKey(uint8_t x, uint8_t y, uint8_t edge, bool enable = true);
void setPixelColor(uint8_t x, uint8_t y, uint32_t color);
void setPixelColor(uint16_t num, uint32_t color);
void show();
void read();
protected:
uint8_t _rows; ///< the number of trellis boards in the Y direction
uint8_t _cols; ///< the number of trellis boards in the X direction
Adafruit_NeoTrellis
*_trelli; ///< a multidimensional array of neotrellis objects
};
#endif

View File

@@ -0,0 +1,65 @@
#include "Adafruit_TFTShield18.h"
/**************************************************************************/
/*!
@brief set up the TFT shield
@param addr optional address the seesaw chip can be found on
@param flow optional flow control pin to use
@returns true on success, false on error
*/
/**************************************************************************/
bool Adafruit_TFTShield18::begin(uint8_t addr, int8_t flow) {
if (!Adafruit_seesaw::begin(addr, flow)) {
return false;
}
pinMode(TFTSHIELD_RESET_PIN, OUTPUT);
pinModeBulk(TFTSHIELD_BUTTON_ALL, INPUT_PULLUP);
return true;
}
/**************************************************************************/
/*!
@brief set the intensity of the backlight
@param value to set the backlight to,
0x0000 = 0% (TFTSHIELD_BACKLIGHT_OFF)
to
0xFFFF = 100% (TFTSHIELD_BACKLIGHT_ON)
*/
/**************************************************************************/
void Adafruit_TFTShield18::setBacklight(uint16_t value) {
uint8_t cmd[] = {0x00, (uint8_t)(value >> 8), (uint8_t)value};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_PWM, cmd, 3);
}
/**************************************************************************/
/*!
@brief set the PWM frequency for the backlight
@param freq the frequency to set the backlight to
*/
/**************************************************************************/
void Adafruit_TFTShield18::setBacklightFreq(uint16_t freq) {
uint8_t cmd[] = {0x0, (uint8_t)(freq >> 8), (uint8_t)freq};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_FREQ, cmd, 3);
}
/**************************************************************************/
/*!
@brief reset the TFT screen by setting the value of the reset pin
@param rst the value to set the reset pin to
*/
/**************************************************************************/
void Adafruit_TFTShield18::tftReset(bool rst) {
digitalWrite(TFTSHIELD_RESET_PIN, rst);
}
/**************************************************************************/
/*!
@brief read all buttons on the wing and return as a 32 bit integer
@returns the value of the buttons
*/
/**************************************************************************/
uint32_t Adafruit_TFTShield18::readButtons() {
return digitalReadBulk(TFTSHIELD_BUTTON_ALL);
}

View File

@@ -0,0 +1,60 @@
#ifndef _TFT_SHIELD_18_H
#define _TFT_SHIELD_18_H
#include "Adafruit_seesaw.h"
#define TFTSHIELD_ADDR 0x2E
#define TFTSHIELD_RESET_PIN 3
#define TFTSHIELD_BACKLIGHT_ON 0xFFFF
#define TFTSHIELD_BACKLIGHT_OFF 0x0000
#define TFTSHIELD_BUTTON_UP_PIN 5
#define TFTSHIELD_BUTTON_UP (1UL << TFTSHIELD_BUTTON_UP_PIN)
#define TFTSHIELD_BUTTON_DOWN_PIN 8
#define TFTSHIELD_BUTTON_DOWN (1UL << TFTSHIELD_BUTTON_DOWN_PIN)
#define TFTSHIELD_BUTTON_LEFT_PIN 6
#define TFTSHIELD_BUTTON_LEFT (1UL << TFTSHIELD_BUTTON_LEFT_PIN)
#define TFTSHIELD_BUTTON_RIGHT_PIN 9
#define TFTSHIELD_BUTTON_RIGHT (1UL << TFTSHIELD_BUTTON_RIGHT_PIN)
#define TFTSHIELD_BUTTON_IN_PIN 7
#define TFTSHIELD_BUTTON_IN (1UL << TFTSHIELD_BUTTON_IN_PIN)
#define TFTSHIELD_BUTTON_1_PIN 10
#define TFTSHIELD_BUTTON_1 (1UL << TFTSHIELD_BUTTON_1_PIN)
#define TFTSHIELD_BUTTON_2_PIN 11
#define TFTSHIELD_BUTTON_2 (1UL << TFTSHIELD_BUTTON_2_PIN)
#define TFTSHIELD_BUTTON_3_PIN 14
#define TFTSHIELD_BUTTON_3 (1UL << TFTSHIELD_BUTTON_3_PIN)
#define TFTSHIELD_BUTTON_ALL \
(TFTSHIELD_BUTTON_UP | TFTSHIELD_BUTTON_DOWN | TFTSHIELD_BUTTON_LEFT | \
TFTSHIELD_BUTTON_RIGHT | TFTSHIELD_BUTTON_IN | TFTSHIELD_BUTTON_1 | \
TFTSHIELD_BUTTON_2 | TFTSHIELD_BUTTON_3)
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with 1.8" tft
shield variant of seesaw helper IC
*/
/**************************************************************************/
class Adafruit_TFTShield18 : public Adafruit_seesaw {
public:
Adafruit_TFTShield18(){};
~Adafruit_TFTShield18(){};
bool begin(uint8_t addr = TFTSHIELD_ADDR, int8_t flow = -1);
void setBacklight(uint16_t value);
void setBacklightFreq(uint16_t freq);
void tftReset(bool rst = true);
uint32_t readButtons();
};
#endif

View File

@@ -0,0 +1,62 @@
#include "Adafruit_miniTFTWing.h"
/**************************************************************************/
/*!
@brief set up the miniTFTWing
@param addr optional address the seesaw chip can be found on
@param flow optional flow control pin to use
@returns true on success, false on error
*/
/**************************************************************************/
bool Adafruit_miniTFTWing::begin(uint8_t addr, int8_t flow) {
if (!Adafruit_seesaw::begin(addr, flow)) {
return false;
}
pinMode(TFTWING_RESET_PIN, OUTPUT);
pinModeBulk(TFTWING_BUTTON_ALL, INPUT_PULLUP);
return true;
}
/**************************************************************************/
/*!
@brief set the value of the backlight
@param value the backlight value to set NOTE: 0xFFFF is all the way on
0x0000 is off.
*/
/**************************************************************************/
void Adafruit_miniTFTWing::setBacklight(uint16_t value) {
uint8_t cmd[] = {0x00, (uint8_t)(value >> 8), (uint8_t)value};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_PWM, cmd, 3);
}
/**************************************************************************/
/*!
@brief set the PWM frequency for the backlight
@param freq the frequency to set the backlight to
*/
/**************************************************************************/
void Adafruit_miniTFTWing::setBacklightFreq(uint16_t freq) {
uint8_t cmd[] = {0x0, (uint8_t)(freq >> 8), (uint8_t)freq};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_FREQ, cmd, 3);
}
/**************************************************************************/
/*!
@brief reset the TFT screen by setting the value of the reset pin
@param rst the value to set the reset pin to
*/
/**************************************************************************/
void Adafruit_miniTFTWing::tftReset(bool rst) {
digitalWrite(TFTWING_RESET_PIN, rst);
}
/**************************************************************************/
/*!
@brief read all buttons on the wing and return as a 32 bit integer
@returns the value of the buttons
*/
/**************************************************************************/
uint32_t Adafruit_miniTFTWing::readButtons() {
return digitalReadBulk(TFTWING_BUTTON_ALL);
}

View File

@@ -0,0 +1,57 @@
#ifndef _MINI_TFT_WING_H
#define _MINI_TFT_WING_H
#include "Adafruit_seesaw.h"
#define TFTWING_ADDR 0x5E
#define TFTWING_RESET_PIN 8
#define TFTWING_BACKLIGHT_ON 0 // inverted output!
#define TFTWING_BACKLIGHT_OFF 0xFFFF // inverted output!
#define TFTWING_BUTTON_UP_PIN 2
#define TFTWING_BUTTON_UP (1UL << TFTWING_BUTTON_UP_PIN)
#define TFTWING_BUTTON_DOWN_PIN 4
#define TFTWING_BUTTON_DOWN (1UL << TFTWING_BUTTON_DOWN_PIN)
#define TFTWING_BUTTON_LEFT_PIN 3
#define TFTWING_BUTTON_LEFT (1UL << TFTWING_BUTTON_LEFT_PIN)
#define TFTWING_BUTTON_RIGHT_PIN 7
#define TFTWING_BUTTON_RIGHT (1UL << TFTWING_BUTTON_RIGHT_PIN)
#define TFTWING_BUTTON_SELECT_PIN 11
#define TFTWING_BUTTON_SELECT (1UL << TFTWING_BUTTON_SELECT_PIN)
#define TFTWING_BUTTON_A_PIN 10
#define TFTWING_BUTTON_A (1UL << TFTWING_BUTTON_A_PIN)
#define TFTWING_BUTTON_B_PIN 9
#define TFTWING_BUTTON_B (1UL << TFTWING_BUTTON_B_PIN)
#define TFTWING_BUTTON_ALL \
(TFTWING_BUTTON_UP | TFTWING_BUTTON_DOWN | TFTWING_BUTTON_LEFT | \
TFTWING_BUTTON_RIGHT | TFTWING_BUTTON_SELECT | TFTWING_BUTTON_A | \
TFTWING_BUTTON_B)
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with mini tft
wing variant of seesaw helper IC
*/
/**************************************************************************/
class Adafruit_miniTFTWing : public Adafruit_seesaw {
public:
Adafruit_miniTFTWing(){};
~Adafruit_miniTFTWing(){};
bool begin(uint8_t addr = TFTWING_ADDR, int8_t flow = -1);
void setBacklight(uint16_t value);
void setBacklightFreq(uint16_t freq);
void tftReset(bool rst = true);
uint32_t readButtons();
};
#endif

View File

@@ -0,0 +1,917 @@
/*!
* @file Adafruit_seesaw.cpp
*
* @mainpage Adafruit seesaw arduino driver
*
* @section intro_sec Introduction
*
* 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!
*
* @section author Author
*
* Written by Dean Miller for Adafruit Industries.
*
* @section license License
*
* BSD license, all text here must be included in any redistribution.
*
*/
#include "Adafruit_seesaw.h"
//#define SEESAW_I2C_DEBUG
/*!
*****************************************************************************************
* @brief Create a seesaw object on a given I2C bus
*
* @param i2c_bus the I2C bus connected to the seesaw, defaults to "Wire"
****************************************************************************************/
Adafruit_seesaw::Adafruit_seesaw(TwoWire *i2c_bus) {
if (i2c_bus == NULL) {
_i2cbus = &Wire;
} else {
_i2cbus = i2c_bus;
}
}
/*!
*****************************************************************************************
* @brief Start the seesaw
*
* This should be called when your sketch is
*connecting to the seesaw
*
* @param addr the I2C address of the seesaw
* @param flow the flow control pin to use
* @param reset pass true to reset the seesaw on startup. Defaults
*to true.
*
* @return true if we could connect to the seesaw, false otherwise
****************************************************************************************/
bool Adafruit_seesaw::begin(uint8_t addr, int8_t flow, bool reset) {
_i2caddr = addr;
_flow = flow;
if (_flow != -1)
::pinMode(_flow, INPUT);
_i2c_init();
if (reset) {
SWReset();
delay(500);
}
uint8_t c = this->read8(SEESAW_STATUS_BASE, SEESAW_STATUS_HW_ID);
if (c != SEESAW_HW_ID_CODE) {
return false;
}
return true;
}
/*!
*******************************************************************
* @brief perform a software reset. This resets all seesaw registers to
*their default values.
* This is called automatically from
*Adafruit_seesaw.begin()
********************************************************************/
void Adafruit_seesaw::SWReset() {
this->write8(SEESAW_STATUS_BASE, SEESAW_STATUS_SWRST, 0xFF);
}
/*!
**************************************************************************
* @brief Returns the available options compiled into the seesaw firmware.
* @return the available options compiled into the seesaw firmware. If the
*option is included, the corresponding bit is set. For example, if the ADC
*module is compiled in then (ss.getOptions() & (1UL << SEESAW_ADC_BASE)) > 0
***********************************************************************/
uint32_t Adafruit_seesaw::getOptions() {
uint8_t buf[4];
this->read(SEESAW_STATUS_BASE, SEESAW_STATUS_OPTIONS, buf, 4);
uint32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
return ret;
}
/*!
*********************************************************************
* @brief Returns the version of the seesaw
* @return The version code. Bits [31:16] will be a date code, [15:0] will
*be the product id.
********************************************************************/
uint32_t Adafruit_seesaw::getVersion() {
uint8_t buf[4];
this->read(SEESAW_STATUS_BASE, SEESAW_STATUS_VERSION, buf, 4);
uint32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
return ret;
}
/*!
**************************************************************************
* @brief Set the mode of a GPIO pin.
*
* @param pin the pin number. On the SAMD09 breakout, this corresponds to
*the number on the silkscreen.
* @param mode the mode to set the pin. One of INPUT, OUTPUT, or
*INPUT_PULLUP.
************************************************************************/
void Adafruit_seesaw::pinMode(uint8_t pin, uint8_t mode) {
if (pin >= 32)
pinModeBulk(0, 1ul << (pin - 32), mode);
else
pinModeBulk(1ul << pin, mode);
}
/*!
***************************************************************************
* @brief Set the output of a GPIO pin
*
* @param pin the pin number. On the SAMD09 breakout, this corresponds to
*the number on the silkscreen.
* @param value the value to write to the GPIO pin. This should be
*HIGH or LOW.
***************************************************************************/
void Adafruit_seesaw::digitalWrite(uint8_t pin, uint8_t value) {
if (pin >= 32)
digitalWriteBulk(0, 1ul << (pin - 32), value);
else
digitalWriteBulk(1ul << pin, value);
}
/*!
****************************************************************************
* @brief Read the current status of a GPIO pin
*
* @param pin the pin number. On the SAMD09 breakout, this corresponds to
*the number on the silkscreen.
*
* @return the status of the pin. HIGH or LOW (1 or 0).
***********************************************************************/
bool Adafruit_seesaw::digitalRead(uint8_t pin) {
if (pin >= 32)
return digitalReadBulkB((1ul << (pin - 32))) != 0;
else
return digitalReadBulk((1ul << pin)) != 0;
}
/*!
****************************************************************************
* @brief read the status of multiple pins on port A.
*
* @param pins a bitmask of the pins to write. On the SAMD09 breakout,
*this corresponds to the number on the silkscreen. For example, passing 0b0110
*will return the values of pins 2 and 3.
*
* @return the status of the passed pins. If 0b0110 was passed and pin 2 is
*high and pin 3 is low, 0b0010 (decimal number 2) will be returned.
*******************************************************************/
uint32_t Adafruit_seesaw::digitalReadBulk(uint32_t pins) {
uint8_t buf[4];
this->read(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK, buf, 4);
uint32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
return ret & pins;
}
/*!
**************************************************************************
* @brief read the status of multiple pins on port B.
*
* @param pins a bitmask of the pins to write.
*
* @return the status of the passed pins. If 0b0110 was passed and pin 2 is
*high and pin 3 is low, 0b0010 (decimal number 2) will be returned.
************************************************************************/
uint32_t Adafruit_seesaw::digitalReadBulkB(uint32_t pins) {
uint8_t buf[8];
this->read(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK, buf, 8);
uint32_t ret = ((uint32_t)buf[4] << 24) | ((uint32_t)buf[5] << 16) |
((uint32_t)buf[6] << 8) | (uint32_t)buf[7];
return ret & pins;
}
/*!
**********************************************************************
* @brief Enable or disable GPIO interrupts on the passed pins
*
* @param pins a bitmask of the pins to write. On the SAMD09 breakout,
*this corresponds to the number on the silkscreen. For example, passing 0b0110
*will enable or disable interrups on pins 2 and 3.
* @param enabled pass true to enable the interrupts on the passed
*pins, false to disable the interrupts on the passed pins.
***********************************************************************/
void Adafruit_seesaw::setGPIOInterrupts(uint32_t pins, bool enabled) {
uint8_t cmd[] = {(uint8_t)(pins >> 24), (uint8_t)(pins >> 16),
(uint8_t)(pins >> 8), (uint8_t)pins};
if (enabled)
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_INTENSET, cmd, 4);
else
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_INTENCLR, cmd, 4);
}
/*!
****************************************************************
* @brief read the analog value on an ADC-enabled pin.
*
* @param pin the number of the pin to read. On the SAMD09 breakout, this
*corresponds to the number on the silkscreen. On the default seesaw firmware on
*the SAMD09 breakout, pins 2, 3, and 4 are ADC-enabled.
*
* @return the analog value. This is an integer between 0 and 1023
***********************************************************************/
uint16_t Adafruit_seesaw::analogRead(uint8_t pin) {
uint8_t buf[2];
uint8_t p;
switch (pin) {
case ADC_INPUT_0_PIN:
p = 0;
break;
case ADC_INPUT_1_PIN:
p = 1;
break;
case ADC_INPUT_2_PIN:
p = 2;
break;
case ADC_INPUT_3_PIN:
p = 3;
break;
default:
return 0;
break;
}
this->read(SEESAW_ADC_BASE, SEESAW_ADC_CHANNEL_OFFSET + p, buf, 2, 500);
uint16_t ret = ((uint16_t)buf[0] << 8) | buf[1];
delay(1);
return ret;
}
/*!
******************************************************************************
* @brief read the analog value on an capacitive touch-enabled pin.
*
* @param pin the number of the pin to read.
*
* @return the analog value. This is an integer between 0 and 1023
****************************************************************************/
uint16_t Adafruit_seesaw::touchRead(uint8_t pin) {
uint8_t buf[2];
uint8_t p = pin;
uint16_t ret = 65535;
do {
delay(1);
this->read(SEESAW_TOUCH_BASE, SEESAW_TOUCH_CHANNEL_OFFSET + p, buf, 2,
1000);
ret = ((uint16_t)buf[0] << 8) | buf[1];
} while (ret == 65535);
return ret;
}
/*!
***************************************************************************
* @brief set the mode of multiple GPIO pins at once.
*
* @param pins a bitmask of the pins to write. On the SAMD09 breakout,
*this corresponds to the number on the silkscreen. For example, passing 0b0110
*will set the mode of pins 2 and 3.
* @param mode the mode to set the pins to. One of INPUT, OUTPUT,
*or INPUT_PULLUP.
************************************************************************/
void Adafruit_seesaw::pinModeBulk(uint32_t pins, uint8_t mode) {
uint8_t cmd[] = {(uint8_t)(pins >> 24), (uint8_t)(pins >> 16),
(uint8_t)(pins >> 8), (uint8_t)pins};
switch (mode) {
case OUTPUT:
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRSET_BULK, cmd, 4);
break;
case INPUT:
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 4);
break;
case INPUT_PULLUP:
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 4);
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_PULLENSET, cmd, 4);
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_SET, cmd, 4);
break;
case INPUT_PULLDOWN:
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 4);
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_PULLENSET, cmd, 4);
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_CLR, cmd, 4);
break;
}
}
/*!
*****************************************************************************************
* @brief set the mode of multiple GPIO pins at once. This supports both
*ports A and B.
*
* @param pinsa a bitmask of the pins to write on port A. On the SAMD09
*breakout, this corresponds to the number on the silkscreen. For example,
*passing 0b0110 will set the mode of pins 2 and 3.
* @param pinsb a bitmask of the pins to write on port B.
* @param mode the mode to set the pins to. One of INPUT, OUTPUT,
*or INPUT_PULLUP.
****************************************************************************************/
void Adafruit_seesaw::pinModeBulk(uint32_t pinsa, uint32_t pinsb,
uint8_t mode) {
uint8_t cmd[] = {(uint8_t)(pinsa >> 24), (uint8_t)(pinsa >> 16),
(uint8_t)(pinsa >> 8), (uint8_t)pinsa,
(uint8_t)(pinsb >> 24), (uint8_t)(pinsb >> 16),
(uint8_t)(pinsb >> 8), (uint8_t)pinsb};
switch (mode) {
case OUTPUT:
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRSET_BULK, cmd, 8);
break;
case INPUT:
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 8);
break;
case INPUT_PULLUP:
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 8);
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_PULLENSET, cmd, 8);
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_SET, cmd, 8);
break;
case INPUT_PULLDOWN:
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 8);
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_PULLENSET, cmd, 8);
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_CLR, cmd, 8);
break;
}
}
/*!
*****************************************************************************************
* @brief write a value to multiple GPIO pins at once.
*
* @param pins a bitmask of the pins to write. On the SAMD09 breakout,
*this corresponds to the number on the silkscreen. For example, passing 0b0110
*will write the passed value to pins 2 and 3.
* @param value pass HIGH to set the output on the passed pins to
*HIGH, low to set the output on the passed pins to LOW.
****************************************************************************************/
void Adafruit_seesaw::digitalWriteBulk(uint32_t pins, uint8_t value) {
uint8_t cmd[] = {(uint8_t)(pins >> 24), (uint8_t)(pins >> 16),
(uint8_t)(pins >> 8), (uint8_t)pins};
if (value)
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_SET, cmd, 4);
else
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_CLR, cmd, 4);
}
/*!
*****************************************************************************************
* @brief write a value to multiple GPIO pins at once. This supports both
*ports A and B
*
* @param pinsa a bitmask of the pins to write on port A. On the SAMD09
*breakout, this corresponds to the number on the silkscreen. For example,
*passing 0b0110 will write the passed value to pins 2 and 3.
* @param pinsb a bitmask of the pins to write on port B.
* @param value pass HIGH to set the output on the passed pins to
*HIGH, low to set the output on the passed pins to LOW.
****************************************************************************************/
void Adafruit_seesaw::digitalWriteBulk(uint32_t pinsa, uint32_t pinsb,
uint8_t value) {
uint8_t cmd[] = {(uint8_t)(pinsa >> 24), (uint8_t)(pinsa >> 16),
(uint8_t)(pinsa >> 8), (uint8_t)pinsa,
(uint8_t)(pinsb >> 24), (uint8_t)(pinsb >> 16),
(uint8_t)(pinsb >> 8), (uint8_t)pinsb};
if (value)
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_SET, cmd, 8);
else
this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_CLR, cmd, 8);
}
/*!
*****************************************************************************************
* @brief write a PWM value to a PWM-enabled pin
*
* @param pin the number of the pin to write. On the SAMD09 breakout, this
*corresponds to the number on the silkscreen. on the default seesaw firmware on
*the SAMD09 breakout, pins 5, 6, and 7 are PWM enabled.
* @param value the value to write to the pin
* @param width the width of the value to write. Defaults to 8. If
*16 is passed a 16 bit value will be written.
****************************************************************************************/
void Adafruit_seesaw::analogWrite(uint8_t pin, uint16_t value, uint8_t width) {
int8_t p = -1;
switch (pin) {
case PWM_0_PIN:
p = 0;
break;
case PWM_1_PIN:
p = 1;
break;
case PWM_2_PIN:
p = 2;
break;
case PWM_3_PIN:
p = 3;
break;
default:
break;
}
if (p > -1) {
if (width == 16) {
uint8_t cmd[] = {(uint8_t)p, (uint8_t)(value >> 8), (uint8_t)value};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_PWM, cmd, 3);
} else {
uint16_t mappedVal = map(value, 0, 255, 0, 65535);
uint8_t cmd[] = {(uint8_t)p, (uint8_t)(mappedVal >> 8),
(uint8_t)mappedVal};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_PWM, cmd, 3);
}
}
}
/*!
* @brief set the PWM frequency of a PWM-enabled pin. Note that on SAMD09,
* SAMD11 boards the frequency will be mapped to closest match
* fixed frequencies. Also note that PWM pins 4 and 5 share a
*timer, and PWM pins 6 and 7 share a timer. Changing the frequency for one pin
*will change the frequency for the other pin that is on the timer.
*
* @param pin the number of the pin to change frequency of. On the SAMD09
* breakout, this corresponds to the number on the silkscreen.
* on the default seesaw firmware on the SAMD09 breakout, pins 5,
*6, and 7 are PWM enabled.
* @param freq the frequency to set.
******************************************************************************/
void Adafruit_seesaw::setPWMFreq(uint8_t pin, uint16_t freq) {
int8_t p = -1;
switch (pin) {
case PWM_0_PIN:
p = 0;
break;
case PWM_1_PIN:
p = 1;
break;
case PWM_2_PIN:
p = 2;
break;
case PWM_3_PIN:
p = 3;
break;
default:
break;
}
if (p > -1) {
uint8_t cmd[] = {(uint8_t)p, (uint8_t)(freq >> 8), (uint8_t)freq};
this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_FREQ, cmd, 3);
}
}
/*!
* @brief Enable the data ready interrupt on the passed sercom. Note that
*both the interrupt module and the passed sercom must be compiled into the
*seesaw firmware for this to function. If both of these things are true, the
*interrupt pin on the seesaw will fire when there is data to be read from the
*passed sercom. On the default seesaw firmeare on the SAMD09 breakout, no
*sercoms are enabled.
*
* @param sercom the sercom to enable the interrupt on.
****************************************************************************************/
void Adafruit_seesaw::enableSercomDataRdyInterrupt(uint8_t sercom) {
_sercom_inten.bit.DATA_RDY = 1;
this->write8(SEESAW_SERCOM0_BASE + sercom, SEESAW_SERCOM_INTEN,
_sercom_inten.reg);
}
/*!
***************************************************************************************
* @brief Disable the data ready interrupt on the passed sercom.
*
* @param sercom the sercom to disable the interrupt on.
****************************************************************************************/
void Adafruit_seesaw::disableSercomDataRdyInterrupt(uint8_t sercom) {
_sercom_inten.bit.DATA_RDY = 0;
this->write8(SEESAW_SERCOM0_BASE + sercom, SEESAW_SERCOM_INTEN,
_sercom_inten.reg);
}
/*!
*****************************************************************************************
* @brief Reads a character from the passed sercom if one is available.
*Note that on the default seesaw firmware on the SAMD09 breakout no sercoms are
*enabled.
*
* @param sercom the sercom to read data from.
* @returns One byte of data
****************************************************************************************/
char Adafruit_seesaw::readSercomData(uint8_t sercom) {
return this->read8(SEESAW_SERCOM0_BASE + sercom, SEESAW_SERCOM_DATA);
}
/*!
*****************************************************************************************
* @brief Set the seesaw I2C address. This will automatically call
*Adafruit_seesaw.begin() with the new address.
*
* @param addr the new address for the seesaw. This must be a valid 7 bit
*I2C address.
****************************************************************************************/
void Adafruit_seesaw::setI2CAddr(uint8_t addr) {
this->EEPROMWrite8(SEESAW_EEPROM_I2C_ADDR, addr);
delay(250);
this->begin(addr); // restart w/ the new addr
}
/*!
*****************************************************************************************
* @brief Read the I2C address of the seesaw
*
* @return the 7 bit I2C address of the seesaw... which you probably
*already know because you just read data from it.
****************************************************************************************/
uint8_t Adafruit_seesaw::getI2CAddr() {
return this->read8(SEESAW_EEPROM_BASE, SEESAW_EEPROM_I2C_ADDR);
}
/*!
*****************************************************************************************
* @brief Write a 1 byte to an EEPROM address
*
* @param addr the address to write to. On the default seesaw firmware on
*the SAMD09 breakout this is between 0 and 63.
* @param val to write between 0 and 255
****************************************************************************************/
void Adafruit_seesaw::EEPROMWrite8(uint8_t addr, uint8_t val) {
this->EEPROMWrite(addr, &val, 1);
}
/*!
*****************************************************************************************
* @brief write a string of bytes to EEPROM starting at the passed address
*
* @param addr the starting address to write the first byte. This will be
*automatically incremented with each byte written.
* @param buf the buffer of bytes to be written.
* @param size the number of bytes to write. Writing past the end
*of available EEPROM may result in undefined behavior.
****************************************************************************************/
void Adafruit_seesaw::EEPROMWrite(uint8_t addr, uint8_t *buf, uint8_t size) {
this->write(SEESAW_EEPROM_BASE, addr, buf, size);
}
/*!
*****************************************************************************************
* @brief Read 1 byte from the specified EEPROM address.
*
* @param addr the address to read from. One the default seesaw firmware
*on the SAMD09 breakout this is between 0 and 63.
*
* @return the value between 0 and 255 that was read from the passed
*address.
****************************************************************************************/
uint8_t Adafruit_seesaw::EEPROMRead8(uint8_t addr) {
return this->read8(SEESAW_EEPROM_BASE, addr);
}
/*!
*****************************************************************************************
* @brief Set the baud rate on SERCOM0.
*
* @param baud the baud rate to set. This is an integer value. Baud rates
*up to 115200 are supported.
****************************************************************************************/
void Adafruit_seesaw::UARTSetBaud(uint32_t baud) {
uint8_t cmd[] = {(uint8_t)(baud >> 24), (uint8_t)(baud >> 16),
(uint8_t)(baud >> 8), (uint8_t)baud};
this->write(SEESAW_SERCOM0_BASE, SEESAW_SERCOM_BAUD, cmd, 4);
}
/*!
*****************************************************************************************
* @brief activate or deactivate a key and edge on the keypad module
*
* @param key the key number to activate
* @param edge the edge to trigger on
* @param enable passing true will enable the passed event,
*passing false will disable it.
****************************************************************************************/
void Adafruit_seesaw::setKeypadEvent(uint8_t key, uint8_t edge, bool enable) {
keyState ks;
ks.bit.STATE = enable;
ks.bit.ACTIVE = (1 << edge);
uint8_t cmd[] = {key, ks.reg};
this->write(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_EVENT, cmd, 2);
}
/**
*****************************************************************************************
* @brief enable the keypad interrupt that fires when events are in the
*fifo.
****************************************************************************************/
void Adafruit_seesaw::enableKeypadInterrupt() {
this->write8(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_INTENSET, 0x01);
}
/**
*****************************************************************************************
* @brief disable the keypad interrupt that fires when events are in the
*fifo.
****************************************************************************************/
void Adafruit_seesaw::disableKeypadInterrupt() {
this->write8(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_INTENCLR, 0x01);
}
/**
*****************************************************************************************
* @brief Get the number of events currently in the fifo
* @return the number of events in the fifo
****************************************************************************************/
uint8_t Adafruit_seesaw::getKeypadCount() {
return this->read8(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_COUNT, 500);
}
/**
*****************************************************************************************
* @brief Read all keyEvents into the passed buffer
*
* @param buf pointer to where the keyEvents should be stored
* @param count the number of events to read
****************************************************************************************/
void Adafruit_seesaw::readKeypad(keyEventRaw *buf, uint8_t count) {
return this->read(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_FIFO, (uint8_t *)buf,
count, 1000);
}
/**
*****************************************************************************************
* @brief Read the temperature of the seesaw board in degrees Celsius.
*NOTE: not all seesaw firmwares have the temperature sensor enabled.
* @return Temperature in degrees Celsius as a floating point value.
****************************************************************************************/
float Adafruit_seesaw::getTemp() {
uint8_t buf[4];
this->read(SEESAW_STATUS_BASE, SEESAW_STATUS_TEMP, buf, 4, 1000);
int32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
return (1.0 / (1UL << 16)) * ret;
}
/**
*****************************************************************************************
* @brief Read the current position of the encoder
* @return The encoder position as a 32 bit signed integer.
****************************************************************************************/
int32_t Adafruit_seesaw::getEncoderPosition() {
uint8_t buf[4];
this->read(SEESAW_ENCODER_BASE, SEESAW_ENCODER_POSITION, buf, 4);
int32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
return ret;
}
/**
*****************************************************************************************
* @brief Set the current position of the encoder
* @param pos the position to set the encoder to.
****************************************************************************************/
void Adafruit_seesaw::setEncoderPosition(int32_t pos) {
uint8_t buf[] = {(uint8_t)(pos >> 24), (uint8_t)(pos >> 16),
(uint8_t)(pos >> 8), (uint8_t)(pos & 0xFF)};
this->write(SEESAW_ENCODER_BASE, SEESAW_ENCODER_POSITION, buf, 4);
}
/**
*****************************************************************************************
* @brief Read the change in encoder position since it was last read.
* @return The encoder change as a 32 bit signed integer.
****************************************************************************************/
int32_t Adafruit_seesaw::getEncoderDelta() {
uint8_t buf[4];
this->read(SEESAW_ENCODER_BASE, SEESAW_ENCODER_DELTA, buf, 4);
int32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
return ret;
}
/**
*****************************************************************************************
* @brief Enable the interrupt to fire when the encoder changes position.
****************************************************************************************/
void Adafruit_seesaw::enableEncoderInterrupt() {
this->write8(SEESAW_ENCODER_BASE, SEESAW_ENCODER_INTENSET, 0x01);
}
/**
*****************************************************************************************
* @brief Disable the interrupt from firing when the encoder changes
*position.
****************************************************************************************/
void Adafruit_seesaw::disableEncoderInterrupt() {
this->write8(SEESAW_ENCODER_BASE, SEESAW_ENCODER_INTENCLR, 0x01);
}
/**
*****************************************************************************************
* @brief Write 1 byte to the specified seesaw register.
*
* @param regHigh the module address register (ex. SEESAW_NEOPIXEL_BASE)
* @param regLow the function address register (ex.
*SEESAW_NEOPIXEL_PIN)
* @param value the value between 0 and 255 to write
****************************************************************************************/
void Adafruit_seesaw::write8(byte regHigh, byte regLow, byte value) {
this->write(regHigh, regLow, &value, 1);
}
/**
*****************************************************************************************
* @brief read 1 byte from the specified seesaw register.
*
* @param regHigh the module address register (ex. SEESAW_STATUS_BASE)
* @param regLow the function address register (ex.
*SEESAW_STATUS_VERSION)
* @param delay a number of microseconds to delay before reading
*out the data. Different delay values may be necessary to ensure the seesaw
*chip has time to process the requested data. Defaults to 125.
*
* @return the value between 0 and 255 read from the passed register
****************************************************************************************/
uint8_t Adafruit_seesaw::read8(byte regHigh, byte regLow, uint16_t delay) {
uint8_t ret;
this->read(regHigh, regLow, &ret, 1, delay);
return ret;
}
/**
*****************************************************************************************
* @brief Initialize I2C. On arduino this just calls i2c->begin()
****************************************************************************************/
void Adafruit_seesaw::_i2c_init() {
#ifdef SEESAW_I2C_DEBUG
Serial.println("I2C Begin");
#endif
_i2cbus->begin();
}
/**
*****************************************************************************************
* @brief Read a specified number of bytes into a buffer from the seesaw.
*
* @param regHigh the module address register (ex. SEESAW_STATUS_BASE)
* @param regLow the function address register (ex.
*SEESAW_STATUS_VERSION)
* @param buf the buffer to read the bytes into
* @param num the number of bytes to read.
* @param delay an optional delay in between setting the read
*register and reading out the data. This is required for some seesaw functions
*(ex. reading ADC data)
****************************************************************************************/
void Adafruit_seesaw::read(uint8_t regHigh, uint8_t regLow, uint8_t *buf,
uint8_t num, uint16_t delay) {
uint8_t pos = 0;
// on arduino we need to read in 32 byte chunks
while (pos < num) {
uint8_t read_now = min(32, num - pos);
_i2cbus->beginTransmission((uint8_t)_i2caddr);
_i2cbus->write((uint8_t)regHigh);
_i2cbus->write((uint8_t)regLow);
#ifdef SEESAW_I2C_DEBUG
Serial.print("I2C read $");
Serial.print((uint16_t)regHigh << 8 | regLow, HEX);
Serial.print(" : ");
#endif
if (_flow != -1)
while (!::digitalRead(_flow))
;
_i2cbus->endTransmission();
// TODO: tune this
delayMicroseconds(delay);
if (_flow != -1)
while (!::digitalRead(_flow))
;
_i2cbus->requestFrom((uint8_t)_i2caddr, read_now);
for (int i = 0; i < read_now; i++) {
buf[pos] = _i2cbus->read();
#ifdef SEESAW_I2C_DEBUG
Serial.print("0x");
Serial.print(buf[pos], HEX);
Serial.print(",");
#endif
pos++;
}
#ifdef SEESAW_I2C_DEBUG
Serial.println();
#endif
}
}
/*!
*****************************************************************************************
* @brief Write a specified number of bytes to the seesaw from the passed
*buffer.
*
* @param regHigh the module address register (ex. SEESAW_GPIO_BASE)
* @param regLow the function address register (ex. SEESAW_GPIO_BULK_SET)
* @param buf the buffer the the bytes from
* @param num the number of bytes to write.
****************************************************************************************/
void Adafruit_seesaw::write(uint8_t regHigh, uint8_t regLow, uint8_t *buf,
uint8_t num) {
_i2cbus->beginTransmission((uint8_t)_i2caddr);
_i2cbus->write((uint8_t)regHigh);
_i2cbus->write((uint8_t)regLow);
_i2cbus->write((uint8_t *)buf, num);
#ifdef SEESAW_I2C_DEBUG
Serial.print("I2C write $");
Serial.print((uint16_t)regHigh << 8 | regLow, HEX);
Serial.print(" : ");
for (int i = 0; i < num; i++) {
Serial.print("0x");
Serial.print(buf[i], HEX);
Serial.print(",");
}
Serial.println();
#endif
if (_flow != -1)
while (!::digitalRead(_flow))
;
_i2cbus->endTransmission();
}
/*!
*****************************************************************************************
* @brief The print wrapper for the seesaw class. Calling this allows you
*to use ss.print() or ss.println() and write to the UART on SERCOM0 of the
*seesaw. Note that this functionality is only available when the UART (sercom)
*module is compiled into the seesaw firmware. On the default seesaw firmware on
*the SAMD09 breakout this functionality is not available.
*
* @param character the character to write.
* @returns The number of bytes written (1)
****************************************************************************************/
size_t Adafruit_seesaw::write(uint8_t character) {
// TODO: add support for multiple sercoms
this->write8(SEESAW_SERCOM0_BASE, SEESAW_SERCOM_DATA, character);
delay(1); // TODO: this can be optimized... it's only needed for longer writes
return 1;
}
/*!
************************************************************************
* @brief The print wrapper for the seesaw class allowing the user to
*print a string. Calling this allows you to use ss.print() or ss.println() and
*write to the UART on SERCOM0 of the seesaw. Note that this functionality is
*only available when the UART (sercom) module is compiled into the seesaw
*firmware. On the default seesaw firmware on the SAMD09 breakout this
*functionality is not available.
*
* @param str the string to write
* @return number of bytes written (not including trailing 0)
*********************************************************************/
size_t Adafruit_seesaw::write(const char *str) {
uint8_t buf[32];
uint8_t len = 0;
while (*str) {
buf[len] = *str;
str++;
len++;
}
this->write(SEESAW_SERCOM0_BASE, SEESAW_SERCOM_DATA, buf, len);
return len;
}
/*!
**********************************************************************
* @brief Write only the module base address register and the function
*address register.
*
* @param regHigh the module address register (ex. SEESAW_STATUS_BASE)
* @param regLow the function address register (ex.
*SEESAW_STATUS_SWRST)
**********************************************************************/
void Adafruit_seesaw::writeEmpty(uint8_t regHigh, uint8_t regLow) {
_i2cbus->beginTransmission((uint8_t)_i2caddr);
_i2cbus->write((uint8_t)regHigh);
_i2cbus->write((uint8_t)regLow);
if (_flow != -1)
while (!::digitalRead(_flow))
;
_i2cbus->endTransmission();
}

View File

@@ -0,0 +1,314 @@
/*!
* @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
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#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,
};
/** GPIO module function addres 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 addres 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 addres registers
*/
enum {
SEESAW_TIMER_STATUS = 0x00,
SEESAW_TIMER_PWM = 0x01,
SEESAW_TIMER_FREQ = 0x02,
};
/** ADC module function addres 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 addres 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 addres 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 addres registers
*/
enum {
SEESAW_TOUCH_CHANNEL_OFFSET = 0x10,
};
/** keypad module function addres 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 = 0x02,
SEESAW_ENCODER_INTENCLR = 0x03,
SEESAW_ENCODER_POSITION = 0x04,
SEESAW_ENCODER_DELTA = 0x05,
};
#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
/*=========================================================================*/
#define SEESAW_HW_ID_CODE 0x55 ///< seesaw HW ID code
#define SEESAW_EEPROM_I2C_ADDR \
0x3F ///< EEPROM address of i2c address to start up with (for devices that
///< support this feature)
/** 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();
void 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 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();
void readKeypad(keyEventRaw *buf, uint8_t count);
float getTemp();
int32_t getEncoderPosition();
int32_t getEncoderDelta();
void enableEncoderInterrupt();
void disableEncoderInterrupt();
void setEncoderPosition(int32_t pos);
virtual size_t write(uint8_t);
virtual size_t write(const char *str);
protected:
uint8_t _i2caddr; /*!< The I2C address used to communicate with the seesaw */
TwoWire *_i2cbus; /*!< The I2C Bus used to communicate with the seesaw */
int8_t _flow; /*!< The flow control pin to use */
void write8(byte regHigh, byte regLow, byte value);
uint8_t read8(byte regHigh, byte regLow, uint16_t delay = 125);
void read(uint8_t regHigh, uint8_t regLow, uint8_t *buf, uint8_t num,
uint16_t delay = 125);
void write(uint8_t regHigh, uint8_t regLow, uint8_t *buf, uint8_t num);
void writeEmpty(uint8_t regHigh, uint8_t regLow);
void _i2c_init();
/*=========================================================================
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
# Adafruit_Seesaw ![Build Status](https://github.com/adafruit/Adafruit_Seesaw/workflows/Arduino%20Library%20CI/badge.svg)
Arduino driver for seesaw multi-use chip
Check out the [documentation](https://adafruit.github.io/Adafruit_Seesaw/html/class_adafruit__seesaw.html) for a listing and explanation of the available methods!

View File

@@ -0,0 +1,34 @@
#include "Adafruit_Crickit.h"
Adafruit_Crickit crickit;
void setup() {
Serial.begin(9600);
if(!crickit.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
//set the PWM freq for all the servo pins
crickit.setPWMFreq(CRICKIT_SERVO1, 50);
}
void loop() {
//set some PWMS
crickit.analogWrite(CRICKIT_SERVO1, 10000);
crickit.analogWrite(CRICKIT_SERVO2, 5000);
crickit.analogWrite(CRICKIT_SERVO3, 20000);
crickit.analogWrite(CRICKIT_SERVO4, 45000);
// read an ADC
Serial.print(crickit.analogRead(CRICKIT_SIGNAL4));
Serial.print(",");
// read a captouch
Serial.println(crickit.touchRead(CRICKIT_TOUCH2));
delay(1);
}

View File

@@ -0,0 +1,37 @@
// Adafruit Crickit Capacitive Touch Demo for Arduino
//
// Displays the value of Adafruit Crickit touchpad values when touched
//
// Tested with the Crickit + micro:bit, all good
#include "Adafruit_Crickit.h"
Adafruit_Crickit crickit;
#define CRICKIT_NUM_TOUCH 4
#define CAPTOUCH_THRESH 500
void setup() {
Serial.begin(9600); // Set up serial monitor - be sure it is set to 9600
Serial.println("Cap Touch Demo");
if(!crickit.begin()) { // Check if Crickit is attached
Serial.println("ERROR Starting crickit"); // If an error, print and
while(1) ; // go to a infinite loop to stop
}
else Serial.println("seesaw started"); // success, we have a Crickit
}
void loop() {
for(int i=0; i<CRICKIT_NUM_TOUCH; i++){ // check each touch input
uint16_t val = crickit.touchRead(i); // read the touch input
if(val > CAPTOUCH_THRESH){ // if the value read is > the threshold
Serial.print("CT"); // print info to serial monitor
Serial.print(i + 1);
Serial.print(" touched! value: ");
Serial.println(val);
}
}
delay(100); // wait tiny bit between checks
}

View File

@@ -0,0 +1,34 @@
#include "Adafruit_Crickit.h"
Adafruit_Crickit crickit;
#define NUM_DRIVES 4
int drives[] = {CRICKIT_DRIVE1, CRICKIT_DRIVE2, CRICKIT_DRIVE3, CRICKIT_DRIVE4};
void setup() {
Serial.begin(115200);
Serial.println("4 Drive demo!");
if(!crickit.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("Crickit started");
//our default frequency is 1khz
for(int i=0; i<NUM_DRIVES; i++)
crickit.setPWMFreq(drives[i], 1000);
}
void loop() {
for(int i=0; i<NUM_DRIVES; i++){
//turn all the way on
crickit.analogWrite(drives[i], CRICKIT_DUTY_CYCLE_OFF);
delay(100);
//turn all the way off
crickit.analogWrite(drives[i], CRICKIT_DUTY_CYCLE_MAX);
delay(100);
}
}

View File

@@ -0,0 +1,27 @@
#include "Adafruit_Crickit.h"
Adafruit_Crickit crickit;
void setup() {
Serial.begin(115200);
Serial.println("1 Drive demo!");
if(!crickit.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("Crickit started");
//our default frequency is 1khz
crickit.setPWMFreq(CRICKIT_DRIVE1, 1000);
}
void loop() {
//turn all the way on
crickit.analogWrite(CRICKIT_DRIVE1, CRICKIT_DUTY_CYCLE_OFF);
delay(500);
//turn all the way off
crickit.analogWrite(CRICKIT_DRIVE1, CRICKIT_DUTY_CYCLE_MAX);
delay(500);
}

View File

@@ -0,0 +1,108 @@
#include "Adafruit_Crickit.h"
#include "seesaw_neopixel.h"
#include "seesaw_servo.h"
#define NEOPIX_PIN 20
#define USE_NEOPIX
seesaw_NeoPixel strip = seesaw_NeoPixel(24, NEOPIX_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_Crickit crickit;
seesaw_Servo s1(&crickit);
seesaw_Servo s2(&crickit);
seesaw_Servo s3(&crickit);
seesaw_Servo s4(&crickit);
#define NUM_SERVOS 4
seesaw_Servo *servos[NUM_SERVOS] = {&s1, &s2, &s3, &s4};
#define COLOR_MAX 150
#define RED strip.Color(COLOR_MAX, 0, 0)
#define YELLOW strip.Color(COLOR_MAX, 150, 0)
#define GREEN strip.Color(0, COLOR_MAX, 0)
#define CYAN strip.Color(0, COLOR_MAX, 255)
#define BLUE strip.Color(0, 0, COLOR_MAX)
#define PURPLE strip.Color(180, 0, COLOR_MAX)
#define CRICKIT_NUM_ADC 8
static const uint8_t crickit_adc[CRICKIT_NUM_ADC] = { CRICKIT_SIGNAL1, CRICKIT_SIGNAL2, CRICKIT_SIGNAL3, CRICKIT_SIGNAL4,
CRICKIT_SIGNAL5, CRICKIT_SIGNAL6, CRICKIT_SIGNAL7, CRICKIT_SIGNAL8 };
#define CRICKIT_NUM_TOUCH 4
static const uint8_t crickit_drive[CRICKIT_NUM_TOUCH] = {CRICKIT_DRIVE1, CRICKIT_DRIVE2, CRICKIT_DRIVE3, CRICKIT_DRIVE4};
#define CAPTOUCH_THRESH 500
void setup() {
Serial.begin(9600);
while(!Serial);
if(!crickit.begin(0x49, A0)){
Serial.println("ERROR Starting crickit");
while(1);
}
else Serial.println("seesaw started");
if(!strip.begin(0x49, A0)){
Serial.println("ERROR Starting neopix");
while(1);
}
Serial.println("neopix started!");
s1.attach(CRICKIT_SERVO1);
s2.attach(CRICKIT_SERVO2);
s3.attach(CRICKIT_SERVO3);
s4.attach(CRICKIT_SERVO4);
}
void loop() {
#ifdef USE_NEOPIX
for(uint16_t i=0; i<strip.numPixels(); i++)
strip.setPixelColor(i, RED);
strip.show();
#endif
for(int i=0; i<CRICKIT_NUM_ADC; i++){
Serial.print(crickit.analogRead(crickit_adc[i]));
Serial.print("\t");
}
Serial.println("");
//TODO: fix drive3 and drive4
for(int i=0; i<4; i++){
uint16_t val = crickit.touchRead(i);
if(val > CAPTOUCH_THRESH){
crickit.analogWrite(crickit_drive[i], (1UL << 16) - 1);
Serial.print("CT");
Serial.print(i + 1);
Serial.print(" touched! value: ");
Serial.println(val);
}
else
crickit.analogWrite(crickit_drive[i], 0);
}
#ifdef USE_NEOPIX
for(uint16_t i=0; i<strip.numPixels(); i++)
strip.setPixelColor(i, GREEN);
strip.show();
#endif
for(int i=0; i<NUM_SERVOS; i++){
seesaw_Servo *s = servos[i];
s->write(1000);
}
delay(500);
#ifdef USE_NEOPIX
for(uint16_t i=0; i<strip.numPixels(); i++)
strip.setPixelColor(i, BLUE);
strip.show();
#endif
for(int i=0; i<NUM_SERVOS; i++){
seesaw_Servo *s = servos[i];
s->write(2000);
}
delay(500);
}

View File

@@ -0,0 +1,51 @@
#include "Adafruit_Crickit.h"
#include "seesaw_motor.h"
Adafruit_Crickit crickit;
seesaw_Motor motor_a(&crickit);
seesaw_Motor motor_b(&crickit);
void setup() {
Serial.begin(115200);
Serial.println("Dual motor demo!");
if(!crickit.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("Crickit started");
//attach motor a
motor_a.attach(CRICKIT_MOTOR_A1, CRICKIT_MOTOR_A2);
//attach motor b
motor_b.attach(CRICKIT_MOTOR_B1, CRICKIT_MOTOR_B2);
}
void loop() {
motor_a.throttle(1);
motor_b.throttle(-1);
delay(1000);
motor_a.throttle(.5);
motor_b.throttle(-.5);
delay(1000);
motor_a.throttle(0);
motor_b.throttle(0);
delay(1000);
motor_a.throttle(-.5);
motor_b.throttle(.5);
delay(1000);
motor_a.throttle(-1);
motor_b.throttle(1);
delay(1000);
motor_a.throttle(0);
motor_b.throttle(0);
delay(500);
}

View File

@@ -0,0 +1,45 @@
#include "Adafruit_Crickit.h"
#include "seesaw_servo.h"
Adafruit_Crickit crickit;
#define NUM_SERVOS 4
//create an array of 4 servos with our crickit object
seesaw_Servo servos[] = { seesaw_Servo(&crickit),
seesaw_Servo(&crickit),
seesaw_Servo(&crickit),
seesaw_Servo(&crickit) };
//these are the pins they will be attached to
int servoPins[] = { CRICKIT_SERVO1, CRICKIT_SERVO2, CRICKIT_SERVO3, CRICKIT_SERVO4 };
void setup() {
Serial.begin(115200);
//begin the crickit
if(!crickit.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("Crickit started");
//attach the servos to their pins
for(int i=0; i<NUM_SERVOS; i++)
servos[i].attach(servoPins[i]); // attaches the servo to the pin
}
void loop() {
//repeat for all 4 servos
for(int i=0; i<NUM_SERVOS; i++){
servos[i].write(0);
delay(1000);
servos[i].write(90);
delay(1000);
servos[i].write(180);
delay(1000);
servos[i].write(90);
delay(1000);
}
}

View File

@@ -0,0 +1,29 @@
#include "Adafruit_Crickit.h"
#include "seesaw_servo.h"
Adafruit_Crickit crickit;
seesaw_Servo myservo(&crickit); // create servo object to control a servo
void setup() {
Serial.begin(115200);
if(!crickit.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("Crickit started");
myservo.attach(CRICKIT_SERVO1); // attaches the servo to CRICKIT_SERVO1 pin
}
void loop() {
myservo.write(0);
delay(1000);
myservo.write(90);
delay(1000);
myservo.write(180);
delay(1000);
myservo.write(90);
delay(1000);
}

View File

@@ -0,0 +1,40 @@
#include "Adafruit_Crickit.h"
Adafruit_Crickit crickit;
#define BUTTON_1 CRICKIT_SIGNAL1
#define BUTTON_2 CRICKIT_SIGNAL2
#define LED_1 CRICKIT_SIGNAL3
#define LED_2 CRICKIT_SIGNAL4
void setup() {
Serial.begin(9600);
if(!crickit.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("Crickit started");
//Two buttons are pullups, connect to ground to activate
crickit.pinMode(BUTTON_1, INPUT_PULLUP);
crickit.pinMode(BUTTON_2, INPUT_PULLUP);
// Two LEDs are outputs, on by default
crickit.pinMode(LED_1, OUTPUT);
crickit.pinMode(LED_2, OUTPUT);
crickit.digitalWrite(LED_1, HIGH);
crickit.digitalWrite(LED_2, HIGH);
}
void loop() {
if(!crickit.digitalRead(BUTTON_1))
crickit.digitalWrite(LED_1, HIGH);
else
crickit.digitalWrite(LED_1, LOW);
if(!crickit.digitalRead(BUTTON_2))
crickit.digitalWrite(LED_2, HIGH);
else
crickit.digitalWrite(LED_2, LOW);
}

View File

@@ -0,0 +1,31 @@
/*
* This example shows how to read and write EEPROM data. Try writing
* then removing power from both devices, commenting out the write, and
* uploading again.
*/
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
void setup() {
Serial.begin(115200);
//while(!Serial);
if(!ss.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
Serial.println("writing 0x0D to register 0x02");
ss.EEPROMWrite8(0x02, 0xD);
delay(500);
Serial.print("reading from register 0x02...0x");
Serial.println(ss.EEPROMRead8(0x02), HEX);
}
void loop() {
//DONT WRITE EEPROM IN A LOOP!!!! YOU WILL DESTROY YOUR FLASH!!!
}

View File

@@ -0,0 +1,130 @@
#include <seesaw_neopixel.h>
#define PIN 10
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
seesaw_NeoPixel strip = seesaw_NeoPixel(12, PIN, NEO_GRB + NEO_KHZ800);
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit...if you must, connect GND first.
void setup() {
Serial.begin(115200);
if(!strip.begin()){
Serial.println("ERROR");
while(1);
}
Serial.println("seesaw started!");
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
// Some example procedures showing how to display to the pixels:
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color(0, 255, 0), 50); // Green
colorWipe(strip.Color(0, 0, 255), 50); // Blue
//colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
// Send a theater pixel chase in...
theaterChase(strip.Color(127, 127, 127), 50); // White
theaterChase(strip.Color(127, 0, 0), 50); // Red
theaterChase(strip.Color(0, 0, 127), 50); // Blue
rainbow(20);
rainbowCycle(20);
theaterChaseRainbow(50);
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
for (int j=0; j<10; j++) { //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

View File

@@ -0,0 +1,79 @@
/* This example shows basic usage of the NeoTrellis.
The buttons will light up various colors when pressed.
The interrupt pin is not used in this example.
*/
#include "Adafruit_NeoTrellis.h"
Adafruit_NeoTrellis trellis;
//define a callback for key presses
TrellisCallback blink(keyEvent evt){
// Check is the pad pressed?
if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) {
trellis.pixels.setPixelColor(evt.bit.NUM, Wheel(map(evt.bit.NUM, 0, trellis.pixels.numPixels(), 0, 255))); //on rising
} else if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_FALLING) {
// or is the pad released?
trellis.pixels.setPixelColor(evt.bit.NUM, 0); //off falling
}
// Turn on/off the neopixels!
trellis.pixels.show();
return 0;
}
void setup() {
Serial.begin(9600);
//while(!Serial);
if (!trellis.begin()) {
Serial.println("Could not start trellis, check wiring?");
while(1);
} else {
Serial.println("NeoPixel Trellis started");
}
//activate all keys and set callbacks
for(int i=0; i<NEO_TRELLIS_NUM_KEYS; i++){
trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING);
trellis.activateKey(i, SEESAW_KEYPAD_EDGE_FALLING);
trellis.registerCallback(i, blink);
}
//do a little animation to show we're on
for (uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
trellis.pixels.setPixelColor(i, Wheel(map(i, 0, trellis.pixels.numPixels(), 0, 255)));
trellis.pixels.show();
delay(50);
}
for (uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
trellis.pixels.setPixelColor(i, 0x000000);
trellis.pixels.show();
delay(50);
}
}
void loop() {
trellis.read(); // interrupt management does all the work! :)
delay(20); //the trellis has a resolution of around 60hz
}
/******************************************/
// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return trellis.pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return trellis.pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return trellis.pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
return 0;
}

View File

@@ -0,0 +1,77 @@
/* This example shows basic usage of the NeoTrellis
with the interrupt pin.
The buttons will light up various colors when pressed.
*/
#include "Adafruit_NeoTrellis.h"
Adafruit_NeoTrellis trellis;
#define INT_PIN 10
// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return trellis.pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return trellis.pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return trellis.pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
//define a callback for key presses
TrellisCallback blink(keyEvent evt){
if(evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING)
trellis.pixels.setPixelColor(evt.bit.NUM, Wheel(map(evt.bit.NUM, 0, trellis.pixels.numPixels(), 0, 255))); //on rising
else if(evt.bit.EDGE == SEESAW_KEYPAD_EDGE_FALLING)
trellis.pixels.setPixelColor(evt.bit.NUM, 0); //off falling
trellis.pixels.show();
return 0;
}
void setup() {
Serial.begin(9600);
//while(!Serial);
pinMode(INT_PIN, INPUT);
if(!trellis.begin()){
Serial.println("could not start trellis");
while(1);
}
else{
Serial.println("trellis started");
}
//activate all keys and set callbacks
for(int i=0; i<NEO_TRELLIS_NUM_KEYS; i++){
trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING);
trellis.activateKey(i, SEESAW_KEYPAD_EDGE_FALLING);
trellis.registerCallback(i, blink);
}
//do a little animation to show we're on
for(uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
trellis.pixels.setPixelColor(i, Wheel(map(i, 0, trellis.pixels.numPixels(), 0, 255)));
trellis.pixels.show();
delay(50);
}
for(uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
trellis.pixels.setPixelColor(i, 0x000000);
trellis.pixels.show();
delay(50);
}
}
void loop() {
if(!digitalRead(INT_PIN)){
trellis.read(false);
}
delay(2);
}

View File

@@ -0,0 +1,102 @@
/* This example shows basic usage of the
MultiTrellis object controlling an array of
NeoTrellis boards
As is this example shows use of two NeoTrellis boards
connected together with the leftmost board having the
default I2C address of 0x2E, and the rightmost board
having the address of 0x2F (the A0 jumper is soldered)
*/
#include "Adafruit_NeoTrellis.h"
#define Y_DIM 4 //number of rows of key
#define X_DIM 8 //number of columns of keys
//create a matrix of trellis panels
Adafruit_NeoTrellis t_array[Y_DIM/4][X_DIM/4] = {
{ Adafruit_NeoTrellis(0x2E), Adafruit_NeoTrellis(0x2F) }
};
/*
If you were using a 2x2 array of NeoTrellis boards, the above lines would be:
#define Y_DIM 8 //number of rows of key
#define X_DIM 8 //number of columns of keys
//create a matrix of trellis panels
Adafruit_NeoTrellis t_array[Y_DIM/4][X_DIM/4] = {
{ Adafruit_NeoTrellis(0x2E), Adafruit_NeoTrellis(0x2F) },
{ Adafruit_NeoTrellis(LOWER_LEFT_I2C_ADDR), Adafruit_NeoTrellis(LOWER_RIGHT_I2C_ADDR) }
};
*/
//pass this matrix to the multitrellis object
Adafruit_MultiTrellis trellis((Adafruit_NeoTrellis *)t_array, Y_DIM/4, X_DIM/4);
// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return seesaw_NeoPixel::Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return seesaw_NeoPixel::Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return seesaw_NeoPixel::Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
return 0;
}
//define a callback for key presses
TrellisCallback blink(keyEvent evt){
if(evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING)
trellis.setPixelColor(evt.bit.NUM, Wheel(map(evt.bit.NUM, 0, X_DIM*Y_DIM, 0, 255))); //on rising
else if(evt.bit.EDGE == SEESAW_KEYPAD_EDGE_FALLING)
trellis.setPixelColor(evt.bit.NUM, 0); //off falling
trellis.show();
return 0;
}
void setup() {
Serial.begin(9600);
//while(!Serial);
if(!trellis.begin()){
Serial.println("failed to begin trellis");
while(1);
}
/* the array can be addressed as x,y or with the key number */
for(int i=0; i<Y_DIM*X_DIM; i++){
trellis.setPixelColor(i, Wheel(map(i, 0, X_DIM*Y_DIM, 0, 255))); //addressed with keynum
trellis.show();
delay(50);
}
for(int y=0; y<Y_DIM; y++){
for(int x=0; x<X_DIM; x++){
//activate rising and falling edges on all keys
trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_RISING, true);
trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_FALLING, true);
trellis.registerCallback(x, y, blink);
trellis.setPixelColor(x, y, 0x000000); //addressed with x,y
trellis.show(); //show all LEDs
delay(50);
}
}
}
void loop() {
trellis.read();
delay(20);
}

View File

@@ -0,0 +1,180 @@
/* This example shows a more complex LED pattern
using a NeoTrellis board.
Note that due to memory requirements this example
will not work on boards with very limited memory such
as the Adafruit Metro (with ATMega328p)
*/
#include "Adafruit_NeoTrellis.h"
Adafruit_NeoTrellis trellis;
#define MAX_RIPPLES 16
#define FALLOFF_TIME 30
#define FALLOFF (0xFF/FALLOFF_TIME)
#define NUM_POINTS 8
#define RIPPLE_RATE .4
#define INT_PIN 10
#define MATRIX_POINT(x,y) ((y)*4+(x))
uint32_t colors[] = {
0xFF0000, 0x00FF00, 0x0000FF,
0xFF00FF, 0x00FFFF, 0xFFFFFF
};
union color {
struct {
uint8_t blue:8;
uint8_t green:8;
uint8_t red:8;
} bit;
uint32_t reg;
};
color matrix[4][4];
struct point {
float x;
float y;
};
struct ripple {
int8_t center;
uint32_t t;
color c;
point points[NUM_POINTS];
};
static struct ripple ripples[MAX_RIPPLES];
//define a callback for key presses
TrellisCallback blink(keyEvent evt){
for(int i=0; i<MAX_RIPPLES; i++){
if(ripples[i].center == -1){
//create a new ripple here
ripples[i].center = evt.bit.NUM;
ripples[i].t = 0;
for(int j=0; j<NUM_POINTS; j++){
ripples[i].points[j].x = NEO_TRELLIS_X(evt.bit.NUM);
ripples[i].points[j].y = NEO_TRELLIS_Y(evt.bit.NUM);
}
ripples[i].c.reg = colors[random(sizeof(colors)/sizeof(uint32_t))];
break;
}
}
return 0;
}
void setup() {
Serial.begin(9600);
//while(!Serial);
pinMode(INT_PIN, INPUT);
randomSeed(analogRead(0));
if(!trellis.begin()){
Serial.println("could not start trellis");
while(1);
}
else{
Serial.println("trellis started");
}
for(int i=0; i<MAX_RIPPLES; i++)
ripples[i].center = -1;
//activate all keys and set callbacks
for(int i=0; i<NEO_TRELLIS_NUM_KEYS; i++){
trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING);
trellis.registerCallback(i, blink);
}
//do a little animation to show we're on
for(uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
trellis.pixels.setPixelColor(i, 0x0000FF);
trellis.pixels.show();
delay(50);
}
for(uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
trellis.pixels.setPixelColor(i, 0x000000);
trellis.pixels.show();
delay(50);
}
}
void processRipples(){
for(int x=0; x<4; x++){
for(int y=0; y<4; y++)
matrix[x][y].reg = 0;
}
bool update = false;
for(int i=0; i<MAX_RIPPLES; i++){
if(ripples[i].center > -1){
update = true;
//push all points out from the center
point *p = ripples[i].points;
p[0].x += RIPPLE_RATE;
p[1].x += RIPPLE_RATE/2;
p[1].y += RIPPLE_RATE/2;
p[2].y += RIPPLE_RATE;
p[3].x -= RIPPLE_RATE/2;
p[3].y += RIPPLE_RATE/2;
p[4].x -= RIPPLE_RATE;
p[5].x -= RIPPLE_RATE/2;
p[5].y -= RIPPLE_RATE/2;
p[6].y -= RIPPLE_RATE;
p[7].x += RIPPLE_RATE/2;
p[7].y -= RIPPLE_RATE/2;
for(int j=0; j<NUM_POINTS; j++){
int x = round(p[j].x);
int y = round(p[j].y);
if(x < 4 && x >= 0 && y < 4 && y >= 0){
byte red = min(255, matrix[x][y].bit.red + ripples[i].c.bit.red);
byte green = min(255, matrix[x][y].bit.green + ripples[i].c.bit.green);
byte blue = min(255, matrix[x][y].bit.blue + ripples[i].c.bit.blue);
matrix[x][y].bit.red = red;
matrix[x][y].bit.green = green;
matrix[x][y].bit.blue = blue;
}
}
ripples[i].t++;
if(ripples[i].t >= FALLOFF_TIME) ripples[i].center = -1;
}
}
if(update){
for(int x=0; x<4; x++){
for(int y=0; y<4; y++)
trellis.pixels.setPixelColor(MATRIX_POINT(x,y), matrix[x][y].reg);
}
trellis.pixels.show();
}
}
void loop() {
if(!digitalRead(INT_PIN)){
trellis.read(false);
}
processRipples();
delay(20);
}

View File

@@ -0,0 +1,44 @@
/*
Fade
This example shows how to fade an LED on pin 6 of a seesaw board using the analogWrite()
function.
The analogWrite() function uses PWM, so if you want to change the pin you're
using, be sure to use another PWM capable pin. On the SAMD09 breakout these are pins 5, 6, and 7
*/
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
int led = 6; // the PWM pin the LED is attached to
int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by
// the setup routine runs once when you press reset:
void setup() {
Serial.begin(9600);
if(!ss.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
}
// the loop routine runs over and over again forever:
void loop() {
// set the brightness of pin 9:
ss.analogWrite(led, brightness);
// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;
// reverse the direction of the fading at the ends of the fade:
if (brightness <= 0 || brightness >= 255) {
fadeAmount = -fadeAmount;
}
// wait for 30 milliseconds to see the dimming effect
delay(30);
}

View File

@@ -0,0 +1,24 @@
/*
* This example shows how read the ADC on a seesaw. The default ADC pins on the SAMD09 Breakout are 2, 3, and 4.
*/
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
void setup() {
Serial.begin(9600);
if(!ss.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
}
void loop() {
Serial.print(ss.analogRead(2));
Serial.print(",");
Serial.println(ss.analogRead(3));
delay(50);
}

View File

@@ -0,0 +1,31 @@
//This example takes UART data given to the seesaw, reads it and then loops it back
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
void setup()
{
Serial.begin(9600);
if(!ss.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
//enable interrupt
ss.enableSercomDataRdyInterrupt();
}
void loop()
{
if(!digitalRead(3)){
char c = ss.readSercomData();
Serial.print(c); //print to arduino console
//delay after reading data
delayMicroseconds(100);
ss.print(c); //send back to the seesaw to print
}
}

View File

@@ -0,0 +1,28 @@
/*
* This example shows how to blink a pin on a seesaw.
* Attach the positive (longer lead) of the LED to pin 15 on the seesaw, and
* the negative lead of the LED to ground through a 1k ohm resistor.
*/
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
void setup() {
Serial.begin(9600);
if(!ss.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
ss.pinMode(15, OUTPUT);
}
void loop() {
ss.digitalWrite(15, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
ss.digitalWrite(15, LOW); // turn the LED off by making the voltage LOW
delay(1000);
}

View File

@@ -0,0 +1,35 @@
/*
* This example shows how set GPIO interrupts on a seesaw.
*/
#include "Adafruit_seesaw.h"
//connect the interrupt pin on the seesaw (pin 8 on samd09 breakout) to this pin on your arduino
#define INT_PIN 3
//the interrupt will fire when this pin on the seesaw changes state
#define SCAN_PIN 9
Adafruit_seesaw ss;
uint32_t mask = ((uint32_t)0b1 << SCAN_PIN);
void setup() {
Serial.begin(9600);
if(!ss.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
ss.pinModeBulk(mask, INPUT_PULLUP);
ss.setGPIOInterrupts(mask, 1);
}
void loop() {
if(!digitalRead(INT_PIN)){
Serial.print("interrupt fired! pin state: ");
Serial.println(ss.digitalRead(SCAN_PIN));
}
}

View File

@@ -0,0 +1,30 @@
/*
* This example shows how to blink multiple pins at once on a seesaw.
* pin 13 is attached to the LED on the samd11 xplained board
*/
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
//blink pins PA11, PA12, PA13
uint32_t mask = ((uint32_t)0b111 << 11);
void setup() {
Serial.begin(9600);
if(!ss.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
ss.pinModeBulk(mask, OUTPUT); //set pin modes
}
void loop() {
ss.digitalWriteBulk(mask, HIGH); //set pins
delay(1000); // wait for a second
ss.digitalWriteBulk(mask, LOW); //clear pins
delay(1000);
}

View File

@@ -0,0 +1,27 @@
/*
* This example shows how to read multiple pins at once on a seesaw.
*/
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
//read pins A8, A9, A10
uint32_t mask = ((uint32_t)0b111 << 8);
void setup() {
Serial.begin(9600);
if(!ss.begin()){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
ss.pinModeBulk(mask, INPUT);
}
void loop() {
Serial.println(ss.digitalReadBulk(mask), BIN);
delay(500);
}

View File

@@ -0,0 +1,29 @@
/*
* This example shows how to read from a seesaw encoder module.
* The available encoder API is:
* int32_t getEncoderPosition();
int32_t getEncoderDelta();
void enableEncoderInterrupt();
void disableEncoderInterrupt();
void setEncoderPosition(int32_t pos);
*/
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
void setup() {
Serial.begin(9600);
if(!ss.begin(0x36)){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
}
void loop() {
Serial.println(ss.getEncoderPosition());
delay(400);
}

View File

@@ -0,0 +1,25 @@
/* this example fades an rgb led based on a read encoder position */
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
void setup() {
Serial.begin(9600);
if(!ss.begin(0x36)){
Serial.println("ERROR!");
while(1);
}
else Serial.println("seesaw started");
// turn off red and green leds
ss.analogWrite(5, 255);
ss.analogWrite(6, 255);
}
void loop() {
uint32_t val = abs(ss.getEncoderPosition());
val = constrain(val*2, 0, 255);
ss.analogWrite(4, 255-val); //write to the led
delay(10);
}

View File

@@ -0,0 +1,86 @@
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
#define BUTTON_RIGHT 6
#define BUTTON_DOWN 7
#define BUTTON_LEFT 9
#define BUTTON_UP 10
#define BUTTON_SEL 14
uint32_t button_mask = (1 << BUTTON_RIGHT) | (1 << BUTTON_DOWN) |
(1 << BUTTON_LEFT) | (1 << BUTTON_UP) | (1 << BUTTON_SEL);
#if defined(ESP8266)
#define IRQ_PIN 2
#elif defined(ESP32)
#define IRQ_PIN 14
#elif defined(ARDUINO_NRF52832_FEATHER)
#define IRQ_PIN 27
#elif defined(TEENSYDUINO)
#define IRQ_PIN 8
#elif defined(ARDUINO_ARCH_WICED)
#define IRQ_PIN PC5
#else
#define IRQ_PIN 5
#endif
void setup() {
Serial.begin(115200);
while(!Serial) {
delay(10);
}
Serial.println("Joy FeatherWing example!");
if(!ss.begin(0x49)){
Serial.println("ERROR! seesaw not found");
while(1);
} else {
Serial.println("seesaw started");
Serial.print("version: ");
Serial.println(ss.getVersion(), HEX);
}
ss.pinModeBulk(button_mask, INPUT_PULLUP);
ss.setGPIOInterrupts(button_mask, 1);
pinMode(IRQ_PIN, INPUT);
}
int last_x = 0, last_y = 0;
void loop() {
int x = ss.analogRead(2);
int y = ss.analogRead(3);
if ( (abs(x - last_x) > 3) || (abs(y - last_y) > 3)) {
Serial.print(x); Serial.print(", "); Serial.println(y);
last_x = x;
last_y = y;
}
/* if(!digitalRead(IRQ_PIN)) { // Uncomment to use IRQ */
uint32_t buttons = ss.digitalReadBulk(button_mask);
//Serial.println(buttons, BIN);
if (! (buttons & (1 << BUTTON_RIGHT))) {
Serial.println("Button A pressed");
}
if (! (buttons & (1 << BUTTON_DOWN))) {
Serial.println("Button B pressed");
}
if (! (buttons & (1 << BUTTON_LEFT))) {
Serial.println("Button Y pressed");
}
if (! (buttons & (1 << BUTTON_UP))) {
Serial.println("Button X pressed");
}
if (! (buttons & (1 << BUTTON_SEL))) {
Serial.println("Button SEL pressed");
}
/* } // Uncomment to use IRQ */
delay(10);
}

View File

@@ -0,0 +1,149 @@
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
#define BUTTON_RIGHT 6
#define BUTTON_DOWN 7
#define BUTTON_LEFT 9
#define BUTTON_UP 10
#define BUTTON_START 14
uint32_t button_mask = (1 << BUTTON_RIGHT) | (1 << BUTTON_DOWN) |
(1 << BUTTON_LEFT) | (1 << BUTTON_UP) | (1 << BUTTON_START);
#if defined(ESP8266)
#define IRQ_PIN 2
#elif defined(ESP32)
#define IRQ_PIN 14
#elif defined(ARDUINO_NRF52832_FEATHER)
#define IRQ_PIN 27
#elif defined(TEENSYDUINO)
#define IRQ_PIN 8
#elif defined(ARDUINO_ARCH_WICED)
#define IRQ_PIN PC5
#else
#define IRQ_PIN 5
#endif
// For the breakout, you can use any 2 or 3 pins
// These pins will also work for the 1.8" TFT shield
#define TFT_CS 6
#define TFT_DC 10
#define TFT_RST 9 // you can also connect this to the Arduino reset
// in which case, set this #define pin to -1!
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
void setup() {
//while (!Serial);
Serial.begin(115200);
if(!ss.begin(0x49)){
Serial.println("ERROR!");
while(1);
}
else{
Serial.println("seesaw started");
Serial.print("version: ");
Serial.println(ss.getVersion(), HEX);
}
ss.pinModeBulk(button_mask, INPUT_PULLUP);
ss.setGPIOInterrupts(button_mask, 1);
pinMode(IRQ_PIN, INPUT);
Serial.println(F("TFT TIME"));
tft.initR(INITR_MINI160x80); // initialize a ST7735S chip, mini display
Serial.println("Initialized");
tft.setRotation(1);
uint16_t time = millis();
tft.fillScreen(ST7735_BLACK);
time = millis() - time;
Serial.println(time, DEC);
delay(500);
// large block of text
tft.fillScreen(ST7735_BLACK);
}
int last_x = 0, last_y = 0;
void loop() {
int y = ss.analogRead(2);
int x = ss.analogRead(3);
if(x > 600 && last_x < 600){
tft.fillTriangle(120, 30, 120, 50, 110, 40, ST7735_WHITE);
Serial.println(F("LEFT"));
}
else if(last_x > 600 && x < 600){
tft.fillTriangle(120, 30, 120, 50, 110, 40, ST7735_BLACK);
}
if(x < 400 && last_x > 400){
tft.fillTriangle(150, 30, 150, 50, 160, 40, ST7735_WHITE);
Serial.println(F("RIGHT"));
}
else if(last_x < 400 && x > 400){
tft.fillTriangle(150, 30, 150, 50, 160, 40, ST7735_BLACK);
}
if(y > 600 && last_y < 600){
tft.fillTriangle(125, 26, 145, 26, 135, 16, ST7735_WHITE);
Serial.println(F("DOWN"));
}
else if(last_y > 600 && y < 600){
tft.fillTriangle(125, 26, 145, 26, 135, 16, ST7735_BLACK);
}
if(y < 400 && last_y > 400){
tft.fillTriangle(125, 53, 145, 53, 135, 63, ST7735_WHITE);
Serial.println(F("UP"));
}
else if(last_y < 400 && y > 400){
tft.fillTriangle(125, 53, 145, 53, 135, 63, ST7735_BLACK);
}
if ( (abs(x - last_x) > 3) || (abs(y - last_y) > 3)) {
Serial.print(x); Serial.print(", "); Serial.println(y);
last_x = x;
last_y = y;
}
if(!digitalRead(IRQ_PIN)){
uint32_t buttons = ss.digitalReadBulk(button_mask);
//Serial.println(buttons, BIN);
if (! (buttons & (1 << BUTTON_DOWN))) {
tft.fillCircle(30, 18, 10, ST7735_GREEN);
Serial.println("B");
}
else tft.fillCircle(30, 18, 10, ST7735_BLACK);
if (! (buttons & (1 << BUTTON_RIGHT))) {
tft.fillCircle(10, 40, 10, ST7735_RED);
Serial.println("A");
}
else tft.fillCircle(10, 40, 10, ST7735_BLACK);
if (! (buttons & (1 << BUTTON_LEFT))) {
tft.fillCircle(50, 40, 10, ST7735_BLUE);
Serial.println("Y");
}
else tft.fillCircle(50, 40, 10, ST7735_BLACK);
if (! (buttons & (1 << BUTTON_UP))) {
tft.fillCircle(30, 57, 10, ST7735_YELLOW);
Serial.println("X");
}
else tft.fillCircle(30, 57, 10, ST7735_BLACK);
if (! (buttons & (1 << BUTTON_START))) {
tft.fillCircle(80, 40, 7, ST7735_WHITE);
Serial.println(F("START"));
}
else tft.fillCircle(80, 40, 7, ST7735_BLACK);
}
delay(10);
}

View File

@@ -0,0 +1,26 @@
#include "Adafruit_seesaw.h"
Adafruit_seesaw ss;
void setup() {
Serial.begin(115200);
Serial.println("seesaw Soil Sensor example!");
if (!ss.begin(0x36)) {
Serial.println("ERROR! seesaw not found");
while(1);
} else {
Serial.print("seesaw started! version: ");
Serial.println(ss.getVersion(), HEX);
}
}
void loop() {
float tempC = ss.getTemp();
uint16_t capread = ss.touchRead(0);
Serial.print("Temperature: "); Serial.print(tempC); Serial.println("*C");
Serial.print("Capacitive: "); Serial.println(capread);
delay(100);
}

View File

@@ -0,0 +1,10 @@
name=Adafruit seesaw Library
version=1.3.0
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=This is a library for the Adafruit seesaw helper IC.
paragraph=This is a library for the Adafruit seesaw helper IC.
category=Other
url=https://github.com/adafruit/Adafruit_Seesaw
architectures=*
depends=Adafruit ST7735 and ST7789 Library

View File

@@ -0,0 +1,82 @@
#ifndef _SEESAW_MOTOR_H
#define _SEESAW_MOTOR_H
#include "Adafruit_seesaw.h"
/**************************************************************************/
/*!
@brief Class that stores state and functions for seesaw motor interface
*/
/**************************************************************************/
class seesaw_Motor {
public:
/**************************************************************************/
/*!
@brief class constructor
@param ss the seesaw object to use
*/
/**************************************************************************/
seesaw_Motor(Adafruit_seesaw *ss) {
_ss = ss;
_pina = -1;
_pinb = -1;
_throttle = 0;
}
~seesaw_Motor() {}
/**************************************************************************/
/*!
@brief attach the motor to the specified PWM pins
@param pina the positive pin to use
@param pinb the negative pin to use
*/
/**************************************************************************/
void attach(int pina, int pinb) {
_pina = pina;
_pinb = pinb;
}
/**************************************************************************/
/*!
@brief set the throttle
@param value the throttle value to set between -1 and 1. Passing 0 will turn
the motor off.
*/
/**************************************************************************/
void throttle(float value) {
if (_pina < 0 || _pinb < 0)
return;
value = constrain(value, -1.0, 1.0);
_throttle = value;
uint16_t absolute = fabs(value) * 65535;
if (value > 0) {
_ss->analogWrite(_pina, 0);
_ss->analogWrite(_pinb, absolute);
} else if (value < 0) {
_ss->analogWrite(_pina, absolute);
_ss->analogWrite(_pinb, 0);
} else {
// both are off
_ss->analogWrite(_pina, 0);
_ss->analogWrite(_pinb, 0);
}
}
/**************************************************************************/
/*!
@brief get the current throttle value
@returns the current throttle value between -1 and 1
*/
/**************************************************************************/
float getThrottle() { return _throttle; }
private:
Adafruit_seesaw *_ss;
int8_t _pina, _pinb;
float _throttle;
};
#endif

View File

@@ -0,0 +1,297 @@
/*-------------------------------------------------------------------------
Arduino library to control a wide variety of WS2811- and WS2812-based RGB
LED devices such as Adafruit FLORA RGB Smart Pixels and NeoPixel strips.
Currently handles 400 and 800 KHz bitstreams on 8, 12 and 16 MHz ATmega
MCUs, with LEDs wired for various color orders. Handles most output pins
(possible exception with upper PORT registers on the Arduino Mega).
Written by Phil Burgess / Paint Your Dragon for Adafruit Industries,
contributions by PJRC, Michael Miller and other members of the open
source community.
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing products
from Adafruit!
-------------------------------------------------------------------------
This file is part of the Adafruit NeoPixel library.
NeoPixel is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
NeoPixel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with NeoPixel. If not, see
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#include "seesaw_neopixel.h"
#include "Adafruit_seesaw.h"
// Constructor when length, pin and type are known at compile-time:
seesaw_NeoPixel::seesaw_NeoPixel(uint16_t n, uint8_t p, neoPixelType t,
TwoWire *Wi)
: Adafruit_seesaw(Wi), begun(false), numLEDs(n), pin(p), brightness(0),
pixels(NULL), endTime(0), type(t) {}
// via Michael Vogt/neophob: empty constructor is used when strand length
// isn't known at compile-time; situations where program config might be
// read from internal flash memory or an SD card, or arrive via serial
// command. If using this constructor, MUST follow up with updateType(),
// updateLength(), etc. to establish the strand type, length and pin number!
seesaw_NeoPixel::seesaw_NeoPixel(TwoWire *Wi)
: Adafruit_seesaw(Wi),
#ifdef NEO_KHZ400
is800KHz(true),
#endif
begun(false), numLEDs(0), numBytes(0), pin(-1), brightness(0),
pixels(NULL), rOffset(1), gOffset(0), bOffset(2), wOffset(1), endTime(0) {
}
seesaw_NeoPixel::~seesaw_NeoPixel() {
if (pixels)
free(pixels);
}
bool seesaw_NeoPixel::begin(uint8_t addr, int8_t flow) {
if (!Adafruit_seesaw::begin(addr, flow))
return false;
updateType(type);
updateLength(numLEDs);
setPin(pin);
return true;
}
void seesaw_NeoPixel::updateLength(uint16_t n) {
if (pixels)
free(pixels); // Free existing data (if any)
// Allocate new data -- note: ALL PIXELS ARE CLEARED
numBytes = n * ((wOffset == rOffset) ? 3 : 4);
if ((pixels = (uint8_t *)malloc(numBytes))) {
memset(pixels, 0, numBytes);
numLEDs = n;
} else {
numLEDs = numBytes = 0;
}
uint8_t buf[] = {(uint8_t)(numBytes >> 8), (uint8_t)(numBytes & 0xFF)};
this->write(SEESAW_NEOPIXEL_BASE, SEESAW_NEOPIXEL_BUF_LENGTH, buf, 2);
}
void seesaw_NeoPixel::updateType(neoPixelType t) {
boolean oldThreeBytesPerPixel = (wOffset == rOffset); // false if RGBW
wOffset = (t >> 6) & 0b11; // See notes in header file
rOffset = (t >> 4) & 0b11; // regarding R/G/B/W offsets
gOffset = (t >> 2) & 0b11;
bOffset = t & 0b11;
is800KHz = (t < 256); // 400 KHz flag is 1<<8
this->write8(SEESAW_NEOPIXEL_BASE, SEESAW_NEOPIXEL_SPEED, is800KHz);
// If bytes-per-pixel has changed (and pixel data was previously
// allocated), re-allocate to new size. Will clear any data.
if (pixels) {
boolean newThreeBytesPerPixel = (wOffset == rOffset);
if (newThreeBytesPerPixel != oldThreeBytesPerPixel)
updateLength(numLEDs);
}
}
void seesaw_NeoPixel::show(void) {
if (!pixels)
return;
// Data latch = 300+ microsecond pause in the output stream. Rather than
// put a delay at the end of the function, the ending time is noted and
// the function will simply hold off (if needed) on issuing the
// subsequent round of data until the latch time has elapsed. This
// allows the mainline code to start generating the next frame of data
// rather than stalling for the latch.
while (!canShow())
;
this->writeEmpty(SEESAW_NEOPIXEL_BASE, SEESAW_NEOPIXEL_SHOW);
endTime = micros(); // Save EOD time for latch on next call
}
// Set the output pin number
void seesaw_NeoPixel::setPin(uint8_t p) {
this->write8(SEESAW_NEOPIXEL_BASE, SEESAW_NEOPIXEL_PIN, p);
pin = p;
}
// Set pixel color from separate R,G,B components:
void seesaw_NeoPixel::setPixelColor(uint16_t n, uint8_t r, uint8_t g,
uint8_t b) {
if (n < numLEDs) {
if (brightness) { // See notes in setBrightness()
r = (r * brightness) >> 8;
g = (g * brightness) >> 8;
b = (b * brightness) >> 8;
}
uint8_t *p;
if (wOffset == rOffset) { // Is an RGB-type strip
p = &pixels[n * 3]; // 3 bytes per pixel
} else { // Is a WRGB-type strip
p = &pixels[n * 4]; // 4 bytes per pixel
p[wOffset] = 0; // But only R,G,B passed -- set W to 0
}
p[rOffset] = r; // R,G,B always stored
p[gOffset] = g;
p[bOffset] = b;
uint8_t len = (wOffset == rOffset ? 3 : 4);
uint16_t offset = n * len;
uint8_t writeBuf[6];
writeBuf[0] = (offset >> 8);
writeBuf[1] = offset;
memcpy(&writeBuf[2], p, len);
this->write(SEESAW_NEOPIXEL_BASE, SEESAW_NEOPIXEL_BUF, writeBuf, len + 2);
}
}
void seesaw_NeoPixel::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b,
uint8_t w) {
if (n < numLEDs) {
if (brightness) { // See notes in setBrightness()
r = (r * brightness) >> 8;
g = (g * brightness) >> 8;
b = (b * brightness) >> 8;
w = (w * brightness) >> 8;
}
uint8_t *p;
if (wOffset == rOffset) { // Is an RGB-type strip
p = &pixels[n * 3]; // 3 bytes per pixel (ignore W)
} else { // Is a WRGB-type strip
p = &pixels[n * 4]; // 4 bytes per pixel
p[wOffset] = w; // Store W
}
p[rOffset] = r; // Store R,G,B
p[gOffset] = g;
p[bOffset] = b;
uint8_t len = (wOffset == rOffset ? 3 : 4);
uint16_t offset = n * len;
uint8_t writeBuf[6];
writeBuf[0] = (offset >> 8);
writeBuf[1] = offset;
memcpy(&writeBuf[2], p, len);
this->write(SEESAW_NEOPIXEL_BASE, SEESAW_NEOPIXEL_BUF, writeBuf, len + 2);
}
}
// Set pixel color from 'packed' 32-bit RGB color:
void seesaw_NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
if (n < numLEDs) {
uint8_t *p, r = (uint8_t)(c >> 16), g = (uint8_t)(c >> 8), b = (uint8_t)c;
if (brightness) { // See notes in setBrightness()
r = (r * brightness) >> 8;
g = (g * brightness) >> 8;
b = (b * brightness) >> 8;
}
if (wOffset == rOffset) {
p = &pixels[n * 3];
} else {
p = &pixels[n * 4];
uint8_t w = (uint8_t)(c >> 24);
p[wOffset] = brightness ? ((w * brightness) >> 8) : w;
}
p[rOffset] = r;
p[gOffset] = g;
p[bOffset] = b;
uint8_t len = (wOffset == rOffset ? 3 : 4);
uint16_t offset = n * len;
uint8_t writeBuf[6];
writeBuf[0] = (offset >> 8);
writeBuf[1] = offset;
memcpy(&writeBuf[2], p, len);
this->write(SEESAW_NEOPIXEL_BASE, SEESAW_NEOPIXEL_BUF, writeBuf, len + 2);
}
}
// Convert separate R,G,B into packed 32-bit RGB color.
// Packed format is always RGB, regardless of LED strand color order.
uint32_t seesaw_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) {
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
// Convert separate R,G,B,W into packed 32-bit WRGB color.
// Packed format is always WRGB, regardless of LED strand color order.
uint32_t seesaw_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
// Query color from previously-set pixel (returns packed 32-bit RGB value)
uint32_t seesaw_NeoPixel::getPixelColor(uint16_t n) const {
if (n >= numLEDs)
return 0; // Out of bounds, return no color.
uint8_t *p;
if (wOffset == rOffset) { // Is RGB-type device
p = &pixels[n * 3];
if (brightness) {
// Stored color was decimated by setBrightness(). Returned value
// attempts to scale back to an approximation of the original 24-bit
// value used when setting the pixel color, but there will always be
// some error -- those bits are simply gone. Issue is most
// pronounced at low brightness levels.
return (((uint32_t)(p[rOffset] << 8) / brightness) << 16) |
(((uint32_t)(p[gOffset] << 8) / brightness) << 8) |
((uint32_t)(p[bOffset] << 8) / brightness);
} else {
// No brightness adjustment has been made -- return 'raw' color
return ((uint32_t)p[rOffset] << 16) | ((uint32_t)p[gOffset] << 8) |
(uint32_t)p[bOffset];
}
} else { // Is RGBW-type device
p = &pixels[n * 4];
if (brightness) { // Return scaled color
return (((uint32_t)(p[wOffset] << 8) / brightness) << 24) |
(((uint32_t)(p[rOffset] << 8) / brightness) << 16) |
(((uint32_t)(p[gOffset] << 8) / brightness) << 8) |
((uint32_t)(p[bOffset] << 8) / brightness);
} else { // Return raw color
return ((uint32_t)p[wOffset] << 24) | ((uint32_t)p[rOffset] << 16) |
((uint32_t)p[gOffset] << 8) | (uint32_t)p[bOffset];
}
}
}
// Returns pointer to pixels[] array. Pixel data is stored in device-
// native format and is not translated here. Application will need to be
// aware of specific pixel data format and handle colors appropriately.
uint8_t *seesaw_NeoPixel::getPixels(void) const { return pixels; }
uint16_t seesaw_NeoPixel::numPixels(void) const { return numLEDs; }
void seesaw_NeoPixel::clear() {
// Clear local pixel buffer
memset(pixels, 0, numBytes);
// Now clear the pixels on the seesaw
uint8_t writeBuf[32];
memset(writeBuf, 0, 32);
for (uint8_t offset = 0; offset < numBytes; offset += 32 - 4) {
writeBuf[0] = (offset >> 8);
writeBuf[1] = offset;
this->write(SEESAW_NEOPIXEL_BASE, SEESAW_NEOPIXEL_BUF, writeBuf, 32);
}
}
void seesaw_NeoPixel::setBrightness(uint8_t b) { brightness = b; }

View File

@@ -0,0 +1,139 @@
/*--------------------------------------------------------------------
This file is part of the Adafruit NeoPixel library.
NeoPixel is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
NeoPixel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with NeoPixel. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------*/
#ifndef SEESAW_NEOPIXEL_H
#define SEESAW_NEOPIXEL_H
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#include <pins_arduino.h>
#endif
#include "Adafruit_seesaw.h"
// The order of primary colors in the NeoPixel data stream can vary
// among device types, manufacturers and even different revisions of
// the same item. The third parameter to the seesaw_NeoPixel
// constructor encodes the per-pixel byte offsets of the red, green
// and blue primaries (plus white, if present) in the data stream --
// the following #defines provide an easier-to-use named version for
// each permutation. e.g. NEO_GRB indicates a NeoPixel-compatible
// device expecting three bytes per pixel, with the first byte
// containing the green value, second containing red and third
// containing blue. The in-memory representation of a chain of
// NeoPixels is the same as the data-stream order; no re-ordering of
// bytes is required when issuing data to the chain.
// Bits 5,4 of this value are the offset (0-3) from the first byte of
// a pixel to the location of the red color byte. Bits 3,2 are the
// green offset and 1,0 are the blue offset. If it is an RGBW-type
// device (supporting a white primary in addition to R,G,B), bits 7,6
// are the offset to the white byte...otherwise, bits 7,6 are set to
// the same value as 5,4 (red) to indicate an RGB (not RGBW) device.
// i.e. binary representation:
// 0bWWRRGGBB for RGBW devices
// 0bRRRRGGBB for RGB
// RGB NeoPixel permutations; white and red offsets are always same
// Offset: W R G B
#define NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2))
#define NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1))
#define NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2))
#define NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1))
#define NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0))
#define NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0))
// RGBW NeoPixel permutations; all 4 offsets are distinct
// Offset: W R G B
#define NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3))
#define NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2))
#define NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3))
#define NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2))
#define NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1))
#define NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1))
#define NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3))
#define NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2))
#define NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3))
#define NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2))
#define NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1))
#define NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1))
#define NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3))
#define NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2))
#define NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3))
#define NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2))
#define NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1))
#define NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1))
#define NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0))
#define NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0))
#define NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0))
#define NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0))
#define NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0))
#define NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0))
// If 400 KHz support is enabled, the third parameter to the constructor
// requires a 16-bit value (in order to select 400 vs 800 KHz speed).
// If only 800 KHz is enabled (as is default on ATtiny), an 8-bit value
// is sufficient to encode pixel color order, saving some space.
#define NEO_KHZ800 0x0000 // 800 KHz datastream
#define NEO_KHZ400 0x0100 // 400 KHz datastream
typedef uint16_t neoPixelType;
class seesaw_NeoPixel : public Adafruit_seesaw {
public:
seesaw_NeoPixel(uint16_t n, uint8_t p = 6,
neoPixelType t = NEO_GRB + NEO_KHZ800, TwoWire *Wi = NULL);
seesaw_NeoPixel(TwoWire *Wi = NULL);
~seesaw_NeoPixel();
bool begin(uint8_t addr = SEESAW_ADDRESS, int8_t flow = -1);
void show(void), setPin(uint8_t p),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w),
setPixelColor(uint16_t n, uint32_t c), setBrightness(uint8_t), clear(),
updateLength(uint16_t n), updateType(neoPixelType t);
uint8_t *getPixels(void) const, getBrightness(void) const;
int8_t getPin(void) { return pin; };
uint16_t numPixels(void) const;
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b),
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
uint32_t getPixelColor(uint16_t n) const;
inline bool canShow(void) { return (micros() - endTime) >= 300L; }
protected:
boolean is800KHz, // ...true if 800 KHz pixels
begun; // true if begin() previously called
uint16_t numLEDs, // Number of RGB LEDs in strip
numBytes; // Size of 'pixels' buffer below (3 or 4 bytes/pixel)
int8_t pin;
uint8_t brightness,
*pixels, // Holds LED color values (3 or 4 bytes each)
rOffset, // Index of red byte within each 3- or 4-byte pixel
gOffset, // Index of green byte
bOffset, // Index of blue byte
wOffset; // Index of white byte (same as rOffset if no white)
uint32_t endTime; // Latch timing reference
uint16_t type;
};
#endif // seesaw_NeoPixel_H

View File

@@ -0,0 +1,91 @@
#include "seesaw_servo.h"
#define MIN_PULSE 3277
#define MAX_PULSE 6554
/**************************************************************************/
/*!
@brief begin the seesaw. This is only necessary if the seesaw is not
already started
@param addr the address to begin on
@param flow the flow control pin to use
@returns true on success, false otherwise
*/
/**************************************************************************/
bool seesaw_Servo::begin(uint8_t addr, int8_t flow) {
return _ss->begin(addr, flow);
}
/**************************************************************************/
/*!
@brief attach the given pin to the next free channel, sets pinMode.
@param pin the pin to use
@returns 0
*/
/**************************************************************************/
uint8_t seesaw_Servo::attach(int pin) {
_pin = pin;
// set frequency to 50 hz
_ss->setPWMFreq(_pin, 50);
_attached = true;
min = MIN_PULSE;
max = MAX_PULSE;
return 0;
}
/**************************************************************************/
/*!
@brief attach the given pin to the next free channel but also sets min and
max values for writes.
@param pin the pin to use
@param min the minimum pulse width value in microseconds
@param max the maximum pulse width value in microseconds
@returns 0
*/
/**************************************************************************/
uint8_t seesaw_Servo::attach(int pin, int min, int max) {
attach(pin);
this->min = min * 3.2767;
this->max = max * 3.2767;
return 0;
}
/**************************************************************************/
/*!
@brief write a value. if value is < 200 its treated as an angle, otherwise
as pulse width in microseconds
@param value the value to write
*/
/**************************************************************************/
void seesaw_Servo::write(int value) {
if (value < 200) {
// angle
uint16_t val = map(value, 0, 180, min, max);
val = constrain(val, min, max);
_ss->analogWrite(_pin, val);
_sval = val;
} else
writeMicroseconds(value);
}
/**************************************************************************/
/*!
@brief get current value
@returns current pulse width as an angle between 0 and 180 degrees
*/
/**************************************************************************/
int seesaw_Servo::read() { return map(_sval, MIN_PULSE, MAX_PULSE, 0, 180); }
/**************************************************************************/
/*!
@brief Write pulse width in microseconds
@param value the value to write
*/
/**************************************************************************/
void seesaw_Servo::writeMicroseconds(int value) {
uint16_t val = 3.2767 * value;
_ss->analogWrite(_pin, val);
_sval = val;
}

View File

@@ -0,0 +1,66 @@
#ifndef _SEESAW_SERVO_H
#define _SEESAW_SERVO_H
#include "Adafruit_seesaw.h"
/**************************************************************************/
/*!
@brief Class that stores state and functions for seesaw servo interface
*/
/**************************************************************************/
class seesaw_Servo {
public:
/**************************************************************************/
/*!
@brief class constructor
@param ss the seesaw object to use
*/
/**************************************************************************/
seesaw_Servo(Adafruit_seesaw *ss) {
_ss = ss;
_attached = false;
}
~seesaw_Servo() {}
bool begin(uint8_t addr = SEESAW_ADDRESS, int8_t flow = -1);
uint8_t attach(int pin);
uint8_t attach(int pin, int min, int max);
/**************************************************************************/
/*!
@brief set attached to false
*/
/**************************************************************************/
void detach() { _attached = false; }
void write(int value);
void writeMicroseconds(int value);
int read();
/**************************************************************************/
/*!
@brief get current value in microseconds
@returns current pulse width in microseconds for this servo
*/
/**************************************************************************/
int readMicroseconds() { return _sval / 3.2768; }
/**************************************************************************/
/*!
@brief check if the servo is attached yet
@returns true if this servo is attached, otherwise false
*/
/**************************************************************************/
bool attached() { return _attached; }
private:
Adafruit_seesaw *_ss;
bool _attached;
uint16_t _sval;
uint8_t _pin;
uint16_t min;
uint16_t max;
};
#endif