From 3b6cc9f0b9422d93f878a5be4d986a6fc6538058 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 14 Mar 2015 22:42:08 -0700 Subject: [PATCH] snapshot, working on perf --- ArduinoKeyboard.h | 9 +- ArduinoKeyboard.ino | 315 ++++++++++++++---------- KeyboardConfig.h | 109 ++------- Makefile | 8 +- _Makefile.master | 2 +- debouncing.cpp | 18 +- sx1509_library.cpp | 572 ++++++++++++++++++++++++++++++++++++++++++++ sx1509_library.h | 337 ++++++++++++++++++++++++++ sx1509_registers.h | 152 ++++++++++++ 9 files changed, 1288 insertions(+), 234 deletions(-) create mode 100644 sx1509_library.cpp create mode 100644 sx1509_library.h create mode 100644 sx1509_registers.h diff --git a/ArduinoKeyboard.h b/ArduinoKeyboard.h index 48783121..8a27e4ca 100644 --- a/ArduinoKeyboard.h +++ b/ArduinoKeyboard.h @@ -1,6 +1,6 @@ #ifndef KeyboardIO_H_ #define KeyboardIO_H_ -#include "Arduino.h" +#include //add your includes for the project KeyboardIO here #include @@ -25,14 +25,13 @@ void setup(); #include "keymaps_generated.h" #include "debouncing.h" - +#include "led_control.h" //extern int usbMaxPower; #define DEBUG_SERIAL 0 - byte matrixState[ROWS][COLS]; - +byte matrixState[ROWS][COLS]; byte charsBeingReported[KEYS_HELD_BUFFER]; // A bit vector for the 256 keys we might conceivably be holding down byte charsReportedLastTime[KEYS_HELD_BUFFER]; // A bit vector for the 256 keys we might conceivably be holding down @@ -73,6 +72,8 @@ void warp_mouse(Key key); // hardware keymap interaction void setup_pins(); +void setup_input_pins(); +void setup_output_pins(); void scan_matrix(); // key matrix diff --git a/ArduinoKeyboard.ino b/ArduinoKeyboard.ino index ec78b500..5c632683 100644 --- a/ArduinoKeyboard.ino +++ b/ArduinoKeyboard.ino @@ -3,22 +3,34 @@ // Copyright 2013 Jesse Vincent // All Rights Reserved. (To be licensed under an opensource license // before the release of the keyboard.io model 01 - +#define DEBUG_SERIAL false /** * TODO: +TEST +TEST2 +#left IO Expander found at 0x00 add mouse inertia add series-of-character macros add series of keystroke macros use a lower-level USB API - * -**/ - +*/ #include "ArduinoKeyboard.h" #include // Don't need this for CLI compilation, but do need it in the IDE -#include +#include "digitalWriteFast.h" +#include +#include "sx1509_library.h" + + + +const byte LEFT_SX1509_ADDRESS = 0x70; // SX1509 I2C address (10) +const byte RIGHT_SX1509_ADDRESS = 0x71; // SX1509 I2C address (11) +sx1509Class leftsx1509(LEFT_SX1509_ADDRESS); +sx1509Class rightsx1509(RIGHT_SX1509_ADDRESS); + + void setup_matrix() { @@ -33,7 +45,6 @@ void reset_matrix() { for (byte col = 0; col < COLS; col++) { for (byte row = 0; row < ROWS; row++) { - matrixState[row][col] <<= 1; } } } @@ -70,16 +81,33 @@ void set_keymap(Key keymapEntry, byte matrixStateEntry) { void scan_matrix() { //scan the Keyboard matrix looking for connections - for (byte row = 0; row < ROWS; row++) { - digitalWriteFast(rowPins[row], LOW); - for (byte col = 0; col < COLS; col++) { + for (byte row = 0; row < LEFT_ROWS; row++) { + leftsx1509.rawWritePin(left_rowpins[row], LOW); + rightsx1509.rawWritePin(right_rowpins[row], LOW); + + + for (byte col = 0; col < LEFT_COLS; col++) { //If we see an electrical connection on I->J, - if (digitalReadFast(colPins[col])) { - matrixState[row][col] |= 0; + matrixState[row][col] <<= 1; + + matrixState[row][(COLS-1)-col] <<= 1; + + if (leftsx1509.rawReadPin(left_colpins[col])) { + matrixState[row][col] |= 0; } else { - matrixState[row][col] |= 1; + matrixState[row][col] |= 1; } + + + + if (rightsx1509.rawReadPin(right_colpins[col])) { + matrixState[row][(COLS - 1) - col] |= 0; + } else { + matrixState[row][(COLS - 1) - col] |= 1; + } + + // while we're inspecting the electrical matrix, we look // to see if the Key being held is a firmware level // metakey, so we can act on it, lest we only discover @@ -87,10 +115,14 @@ void scan_matrix() // through the matrix scan - set_keymap(keymaps[active_keymap][row][col], matrixState[row][col]); + // set_keymap(keymaps[active_keymap][row][col], matrixState[row][col]); + // set_keymap(keymaps[active_keymap][row][(COLS - 1) - col], matrixState[row][(COLS - 1) - col]); + } - digitalWriteFast(rowPins[row], HIGH); + leftsx1509.rawWritePin(left_rowpins[row], HIGH); + + rightsx1509.rawWritePin(right_rowpins[row], HIGH); } } @@ -99,124 +131,127 @@ void scan_matrix() void command_reboot_bootloader() { - Keyboard.println("Rebooting to bootloader"); - Serial.end(); + Keyboard.println("Rebooting to bootloader"); + Serial.end(); - // Set the magic bits to get a Caterina-based device - // to reboot into the bootloader and stay there, rather - // than run move onward - // - // These values are the same as those defined in - // Caterina.c - - uint16_t bootKey = 0x7777; - uint16_t *const bootKeyPtr = (uint16_t *)0x0800; + // Set the magic bits to get a Caterina-based device + // to reboot into the bootloader and stay there, rather + // than run move onward + // + // These values are the same as those defined in + // Caterina.c + + uint16_t bootKey = 0x7777; + uint16_t *const bootKeyPtr = (uint16_t *)0x0800; - // Stash the magic key - *bootKeyPtr = bootKey; + // Stash the magic key + *bootKeyPtr = bootKey; - // Set a watchdog timer - wdt_enable(WDTO_120MS); + // Set a watchdog timer + wdt_enable(WDTO_120MS); - while(1) {} // This infinite loop ensures nothing else - // happens before the watchdog reboots us + while (1) {} // This infinite loop ensures nothing else + // happens before the watchdog reboots us } void command_plugh() { - commandMode = !commandMode; - if (commandMode) { - Keyboard.println(""); - Keyboard.println("Entering command mode!"); - - } else { - Keyboard.println("Leaving command mode!"); - Keyboard.println(""); - } + commandMode = !commandMode; + if (commandMode) { + Keyboard.println(""); + Keyboard.println("Entering command mode!"); + + } else { + Keyboard.println("Leaving command mode!"); + Keyboard.println(""); } +} void setup_command_mode() { - commandBufferSize=0; - commandMode = false; - commandPromptPrinted = false; + commandBufferSize = 0; + commandMode = false; + commandPromptPrinted = false; } boolean command_ends_in_return() { if ( - commandBuffer[commandBufferSize-1] == KEY_ENTER || - commandBuffer[commandBufferSize-1] == KEY_RETURN ) { - return true; + commandBuffer[commandBufferSize - 1] == KEY_ENTER || + commandBuffer[commandBufferSize - 1] == KEY_RETURN ) { + return true; } else { - return false; + return false; } } boolean is_command_buffer(byte* myCommand) { - if (!command_ends_in_return()) { + if (!command_ends_in_return()) { return false; + } + int i = 0; + do { + if (commandBuffer[i] != myCommand[i]) { + return false; } - int i = 0; - do { - if (commandBuffer[i] != myCommand[i]) { - return false; - } - } while (myCommand[++i] != NULL); - return true; + } while (myCommand[++i] != NULL); + return true; } -void process_command_buffer(){ +void process_command_buffer() { if (!command_ends_in_return()) { - return; + return; } - // This is the only command we might want to execute when - // we're not in command mode, as it's the only way to toggle + // This is the only command we might want to execute when + // we're not in command mode, as it's the only way to toggle // command mode on - static byte cmd_plugh[] = {KEY_P,KEY_L,KEY_U,KEY_G,KEY_H,NULL}; + static byte cmd_plugh[] = {KEY_P, KEY_L, KEY_U, KEY_G, KEY_H, NULL}; if (is_command_buffer(cmd_plugh)) { - command_plugh(); + command_plugh(); } // if we've toggled command mode off, get out of here. if (!commandMode) { - commandBufferSize=0; - return; + commandBufferSize = 0; + return; } - - // Handle all the other commands here - static byte cmd_reboot_bootloader[] = { KEY_B, KEY_O, KEY_O, KEY_T, KEY_L, KEY_O, KEY_A, KEY_D, KEY_E, KEY_R, NULL}; - static byte cmd_version[] = { KEY_V, KEY_E, KEY_R, KEY_S, KEY_I, KEY_O, KEY_N, NULL}; - - if(is_command_buffer(cmd_reboot_bootloader)) { - command_reboot_bootloader(); - } else if (is_command_buffer(cmd_version)) { - Keyboard.println(""); - Keyboard.print("This is Keyboardio Firmware "); - Keyboard.println(VERSION); - } + // Handle all the other commands here + static byte cmd_reboot_bootloader[] = { KEY_B, KEY_O, KEY_O, KEY_T, KEY_L, KEY_O, KEY_A, KEY_D, KEY_E, KEY_R, NULL}; + static byte cmd_version[] = { KEY_V, KEY_E, KEY_R, KEY_S, KEY_I, KEY_O, KEY_N, NULL}; - if (!commandPromptPrinted ){ + if (is_command_buffer(cmd_reboot_bootloader)) { + command_reboot_bootloader(); + } else if (is_command_buffer(cmd_version)) { + Keyboard.println(""); + Keyboard.print("This is Keyboardio Firmware "); + Keyboard.println(VERSION); + } + + + if (!commandPromptPrinted ) { Keyboard.print(">>> "); commandPromptPrinted = true; - commandBufferSize=0; + commandBufferSize = 0; } } void setup() { - wdt_disable(); - + wdt_disable(); + delay(5000); + Serial.begin(9600); //usbMaxPower = 100; Keyboard.begin(); Mouse.begin(); + setup_leds(); + update_leds(); setup_command_mode(); setup_matrix(); setup_pins(); - Serial.begin(9600); + primary_keymap = load_primary_keymap(); } @@ -224,14 +259,13 @@ String myApp; void loop() { - if(Serial.available()) { - myApp = Serial.readString(); - myApp.trim(); - } + // if(Serial.available()) { + // myApp = Serial.readString(); + // myApp.trim(); + // } active_keymap = primary_keymap; scan_matrix(); send_key_events(); - reset_matrix(); reset_key_report(); } @@ -348,10 +382,9 @@ void record_key_being_pressed(byte character) void reset_key_report() { - for (byte i = 0; i < KEYS_HELD_BUFFER; i++) { - charsReportedLastTime[i] = charsBeingReported[i]; - charsBeingReported[i] = 0x00; - } + memcpy( charsReportedLastTime,charsBeingReported, KEYS_HELD_BUFFER); + memset(charsBeingReported,0,KEYS_HELD_BUFFER); + } @@ -419,21 +452,21 @@ void send_key_events() } else { if (String("Slack") == myApp) { - if (key_is_pressed(switchState)) { - record_key_being_pressed(mappedKey.rawKey); + if (key_is_pressed(switchState)) { + record_key_being_pressed(mappedKey.rawKey); if (key_toggled_on (switchState)) { - Keyboard.print("Never gonna give you up!"); + Keyboard.print("Never gonna give you up!"); } - } - } else { - if (key_is_pressed(switchState)) { - record_key_being_pressed(mappedKey.rawKey); - if (key_toggled_on (switchState)) { - press_key(mappedKey); } - } else if (key_toggled_off (switchState)) { + } else { + if (key_is_pressed(switchState)) { + record_key_being_pressed(mappedKey.rawKey); + if (key_toggled_on (switchState)) { + press_key(mappedKey); + } + } else if (key_toggled_off (switchState)) { release_key(mappedKey); - } + } } } } @@ -443,47 +476,71 @@ void send_key_events() } void press_key(Key mappedKey) { - Keyboard.press(mappedKey.rawKey); - if (commandBufferSize>=31){ - commandBufferSize=0; - } - commandBuffer[commandBufferSize++]=mappedKey.rawKey; + Keyboard.press(mappedKey.rawKey); + if (commandBufferSize >= 31) { + commandBufferSize = 0; + } + commandBuffer[commandBufferSize++] = mappedKey.rawKey; - if( mappedKey.rawKey == KEY_ENTER || - mappedKey.rawKey == KEY_RETURN ) { - commandPromptPrinted=false; - process_command_buffer(); - commandBufferSize=0; - } + if ( mappedKey.rawKey == KEY_ENTER || + mappedKey.rawKey == KEY_RETURN ) { + commandPromptPrinted = false; + process_command_buffer(); + commandBufferSize = 0; + } } -void release_key(Key mappedKey){ - Keyboard.release(mappedKey.rawKey); +void release_key(Key mappedKey) { + Keyboard.release(mappedKey.rawKey); } -// Hardware initialization -void setup_pins() -{ - setup_output_pins(); - setup_input_pins(); +void make_input(sx1509Class sx1509, int pin) { + sx1509.pinDir(pin, INPUT); // Set SX1509 pin 1 as an input + sx1509.writePin(pin, HIGH); // Activate pull-up + + } -void setup_output_pins() { - //set up the row pins as outputs - for (byte row = 0; row < ROWS; row++) { - pinMode(rowPins[row], OUTPUT); - digitalWriteFast(rowPins[row], HIGH); - } +void make_output(sx1509Class sx1509, int pin) { + sx1509.pinDir(pin, OUTPUT); + sx1509.writePin(pin, HIGH); + } -void setup_input_pins { - for (byte col = 0; col < COLS; col++) { - pinMode(colPins[col], INPUT); - digitalWriteFast(colPins[col], HIGH); - //drive em high by default s it seems to be more reliable than driving em low + + +void setup_pins() { + if (rightsx1509.init()) { // init ok + + for (int i = 0; i < RIGHT_ROWS; i++) { + make_output(rightsx1509, right_rowpins[i]); + } + + for (int j = 0; j < RIGHT_COLS; j++) { + make_input(rightsx1509, right_colpins[j]); + } + + + } + + if (leftsx1509.init()) { // init ok + + + for (int i = 0; i < LEFT_ROWS; i++) { + make_output(leftsx1509, left_rowpins[i]); + } + + for (int j = 0; j < LEFT_COLS; j++) { + make_input(leftsx1509, left_colpins[j]); + } + } + + + + } diff --git a/KeyboardConfig.h b/KeyboardConfig.h index 0c6934e2..cf607edd 100644 --- a/KeyboardConfig.h +++ b/KeyboardConfig.h @@ -1,112 +1,53 @@ //#define DEBUG_SERIAL false +#ifndef KEYBOARD_CONFIG_H +#define KEYBOARD_CONFIG_H +#include "WS2812.h" #define EEPROM_KEYMAP_LOCATION 0 -#define MODEL01keytest true +#define MODEL01 true -#ifdef MODEL00 -#define COLS 14 +#ifdef SYMMETRIC60 #define ROWS 5 -static const byte colPins[COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, A0 }; -static const byte rowPins[ROWS] = { A5, A4, A3, A2, A1 }; +#define COLS 14 +static const byte colPins[COLS] = { +A0, 3,13, 5, 10, 9, 8, 6, 12, 4, 11, 1, 0, 2 }; +static const byte rowPins[ROWS] = { A5,A4,A3,A2,A1}; +#define LED_DATA_PIN 7 +#define LED_COUNT 0 +static const int key_led_map[ROWS][COLS] = {}; #endif -#ifdef MODEL00bis -#define COLS 14 -#define ROWS 5 -static const byte colPins[COLS] = { 0,1, 2, 3, 4, 5,6,7, 8, 9, 10,11,12, A0}; +#ifdef MODEL01 -static const byte rowPins[ROWS] = { A1,A2,A3,A4,A5}; -#endif +int RIGHT_COLS=8; +int RIGHT_ROWS=4; -#ifdef MODEL00piersjesse -#define COLS 16 -#define ROWS 4 -static const byte colPins[COLS] = { - MOSI, - SCK, - 1, - 0, - 2, - 3, - 4, - 9, - 8, - 5, - 6, - 7, - MISO, - 12, - A5, - A4 - -}; -static const byte rowPins[ROWS] = { A0, A1,A2,A3 }; +int LEFT_COLS=8; +int LEFT_ROWS=4; +int left_colpins[]={7,6,5,4,3,2,1,0}; +int left_rowpins[]={8,9,10,11}; -#endif +int right_colpins[]={0,1,2,3,4,5,6,7}; +int right_rowpins[]={8,9,10,11}; -#ifdef MODEL01keytest -#define COLS 16 -#define ROWS 4 -static const byte colPins[COLS] = { - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - SCK, - MISO, - A5, - A4, - -}; -static const byte rowPins[ROWS] = { A0, A1,A2,A3 }; -#endif -#ifdef MODEL00piers #define COLS 16 -#define ROWS 5 - -static const byte colPins[COLS] = { - - 3, - A4, - A5, - MISO, - SCK, - 1, - MOSI, - 2, - 4, - 5, - 7, - 8, - 9, - 10, - 0, - 12, -}; -static const byte rowPins[ROWS] = { A0, A1,A2,A3 }; +#define ROWS 4 #endif -//#static const byte colPins[COLS] = { 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; -//#static const byte rowPins[ROWS] = { A2, A3, A4, A5, 15 }; + // if we're sticking to boot protocol, these could all be 6 + mods // but *mumble* #define KEYS_HELD_BUFFER 12 + +#endif diff --git a/Makefile b/Makefile index 5a22bead..208adacc 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,15 @@ # Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile #BOARD_TAG = keyboardio -BOARD = micro +BOARD = symmetric60 PORT = /dev/cu.usbmodem1421 ARDUINO_LIBS = +THIRD_PARTY_HARDWARE=hardware/keyboardio/avr #ARDUINO_CORE_PATH = hardware/keyboardio/cores/keyboardio #ALTERNATE_CORE = keyboardio GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always) -include _Makefile.Master - - +include ./_Makefile.Master +include ./blank astyle: astyle --style=linux ArduinoKeyboard.ino *.h diff --git a/_Makefile.master b/_Makefile.master index 8d2550b9..e949c21a 100644 --- a/_Makefile.master +++ b/_Makefile.master @@ -700,4 +700,4 @@ upload_monitor : upload monitor upmonitor: upload_monitor --include $(wildcard $(BUILD_DIR)/.*.dep)) +#-include $(wildcard $(BUILD_DIR)/.*.dep)) diff --git a/debouncing.cpp b/debouncing.cpp index b7bfaf49..14e73564 100644 --- a/debouncing.cpp +++ b/debouncing.cpp @@ -6,7 +6,7 @@ boolean key_was_pressed (byte keyState) { - if ( byte((keyState >> 4)) ^ B00001111 ) { + if ( byte((keyState >> 7)) ^ B00000001 ) { return false; } else { return true; @@ -16,18 +16,16 @@ boolean key_was_pressed (byte keyState) boolean key_was_not_pressed (byte keyState) { - if ( byte((keyState >> 4)) ^ B00000000 ) { - return false; - } else { - return true; - } + + return !key_was_pressed(keyState); + } boolean key_is_pressed (byte keyState) { - if ( byte((keyState << 4)) ^ B11110000 ) { + if ( byte((keyState << 7)) ^ B10000000 ) { return false; } else { return true; @@ -35,12 +33,8 @@ boolean key_is_pressed (byte keyState) } boolean key_is_not_pressed (byte keyState) { + return(!key_is_pressed(keyState)); - if ( byte((keyState << 4)) ^ B00000000 ) { - return false; - } else { - return true; - } } boolean key_toggled_on(byte keyState) diff --git a/sx1509_library.cpp b/sx1509_library.cpp new file mode 100644 index 00000000..2d7282cc --- /dev/null +++ b/sx1509_library.cpp @@ -0,0 +1,572 @@ +/* + sx1509_library.cpp + Code file for the SX1509 Arduino library. + + by: Jim Lindblom + SparkFun Electronics + date: December 13, 2012 + + license: Beerware. Feel free to use it, with or without attribution, in + your own projects. If you find it helpful, buy me a beer next time you + see me at the local pub. + + In here you'll find the Arduino code used to interface with the SX1509 I2C + 16 I/O expander. There are functions to take advantage of everything the + SX1509 provides - input/output setting, writing pins high/low, reading + the input value of pins, LED driver utilities (blink, breath, pwm), and + keypad engine utilites. + + See the header file (sx1509_library.h) for detailed descriptions of each of + the sx1509Class methods. + + For example uses of these functions, see the Arduino example codes in the + ./examples/ folder. +*/ + +#include +#include "Arduino.h" +#include "sx1509_library.h" +#include "sx1509_registers.h" + +sx1509Class::sx1509Class(byte address, byte resetPin, byte interruptPin, byte oscillatorPin) +{ + // Store the received parameters into member variables + deviceAddress = address; + pinInterrupt = interruptPin; + pinOscillator = oscillatorPin; + pinReset = resetPin; +} + +byte sx1509Class::init(void) +{ + if (pinInterrupt != 255) + { + pinMode(pinInterrupt, INPUT_PULLUP); + } + + // Begin I2C + Wire.begin(); + + // If the reset pin is connected + if (pinReset != 255) + reset(1); + else + reset(0); + + // Communication test. We'll read from two registers with different + // default values to verify communication. + unsigned int testRegisters = 0; + testRegisters = readWord(REG_INTERRUPT_MASK_A); // This should return 0xFF00 + // Then read a byte that should be 0x00 + if (testRegisters == 0xFF00) + return 1; + else + return 0; +} + +void sx1509Class::reset(bool hardware) +{ + // if hardware bool is set + if (hardware) + { + // Check if bit 2 of REG_MISC is set + // if so nReset will not issue a POR, we'll need to clear that bit first + byte regMisc = readByte(REG_MISC); + if (regMisc & (1<<2)) + { + regMisc &= ~(1<<2); + writeByte(REG_MISC, regMisc); + } + // Reset the SX1509, the pin is active low + pinMode(pinReset, OUTPUT); // set reset pin as output + digitalWrite(pinReset, LOW); // pull reset pin low + delay(1); // Wait for the pin to settle + digitalWrite(pinReset, HIGH); // pull reset pin back high + } + else + { + // Software reset command sequence: + writeByte(REG_RESET, 0x12); + writeByte(REG_RESET, 0x34); + } +} + +void sx1509Class::pinDir(byte pin, byte inOut) +{ + unsigned int tempRegDir = readWord(REG_DIR_B); + // The SX1509 RegDir registers: REG_DIR_B, REG_DIR_A + // 0: IO is configured as an output + // 1: IO is configured as an input + // Flip inOut, in arduino.h INPUT = 0, OUTPUT = 1 + if (!inOut) tempRegDir |= (1<= 8) senseRegister = REG_SENSE_HIGH_B; + else senseRegister = REG_SENSE_HIGH_A; + + tempWord = readWord(senseRegister); + tempWord &= ~(0b11<> 8); + Wire.write(writeValue & 0x00FF); + Wire.endTransmission(); +} + +// writeBytes(byte firstRegisterAddress, byte * writeArray, byte length) +// This function writes an array of bytes, beggining at a specific adddress +// - firstRegisterAddress is the initial register to be written. +// - All writes following will be at incremental register addresses. +// - writeArray should be an array of byte values to be written. +// - length should be the number of bytes to be written. +// - no return value. +void sx1509Class::writeBytes(byte firstRegisterAddress, byte * writeArray, byte length) +{ + Wire.beginTransmission(deviceAddress); + Wire.write(firstRegisterAddress); + for (int i=0; ihigh, which should +// reset all LED counters. Bit 2 of REG_MISC is again cleared, returning +// nReset pin to POR functionality +// ----------------------------------------------------------------------------- + void sync(void); + +// ----------------------------------------------------------------------------- +// debounceConfig(byte configValue): This method configures the debounce time of +// every input. +// +// Input: +// - configValue: A 3-bit value configuring the debounce time. +// 000: 0.5ms * 2MHz/fOSC +// 001: 1ms * 2MHz/fOSC +// 010: 2ms * 2MHz/fOSC +// 011: 4ms * 2MHz/fOSC +// 100: 8ms * 2MHz/fOSC +// 101: 16ms * 2MHz/fOSC +// 110: 32ms * 2MHz/fOSC +// 111: 64ms * 2MHz/fOSC +// +// Note: fOSC is set with the configClock function. It defaults to 2MHz. +// ----------------------------------------------------------------------------- + void debounceConfig(byte configVaule); + +// ----------------------------------------------------------------------------- +// debounceEnable(byte pin): This method enables debounce on SX1509 input pin. +// +// Input: +// - pin: The SX1509 pin to be debounced. Should be between 0 and 15. +// +// Note: debounceConfig() should be called before this, to configure the clock +// and other debounce parameters. +// ----------------------------------------------------------------------------- + void debounceEnable(byte pin); + +// ----------------------------------------------------------------------------- +// enableInterrupt(byte pin, byte riseFall): This function sets up an interrupt +// on a pin. Interrupts can occur on all SX1509 pins, and can be generated +// on rising, falling, or both. +// +// Inputs: +// -pin: SX1509 input pin that will generate an input. Should be 0-15. +// -riseFall: Configures if you want an interrupt generated on rise fall or +// both. For this param, send the pin-change values previously defined +// by Arduino: +// #define CHANGE 1 <-Both +// #define FALLING 2 <- Falling +// #define RISING 3 <- Rising +// +// Note: This function does not set up a pin as an input, or configure its +// pull-up/down resistors! Do that before (or after). +// ----------------------------------------------------------------------------- + void enableInterrupt(byte pin, byte riseFall); + +// ----------------------------------------------------------------------------- +// interruptSource(void): Returns an unsigned int representing which pin caused +// an interrupt. +// +// Output: 16-bit value, with a single bit set representing the pin(s) that +// generated an interrupt. E.g. a return value of 0x0104 would mean pins 8 +// and 3 (bits 8 and 3) have generated an interrupt. +// +// Note: This function also clears all interrupts +// ----------------------------------------------------------------------------- + unsigned int interruptSource(void); + +// ----------------------------------------------------------------------------- +// configClock(byte oscSource, byte oscPinFunction, byte oscFreqOut, +// byte oscDivider): This function configures the oscillator source/speed +// and the clock, which is used to drive LEDs and time debounces. +// +// Inputs: +// - oscSource: Choose either internal 2MHz oscillator or an external signal +// applied to the OSCIO pin. +// - INTERNAL_CLOCK and EXTERNAL_CLOCK are defined in the header file. +// Use those. +// - This value defaults to internal. +// - oscPinFunction: Allows you to set OSCIO as an input or output. +// - You can use Arduino's INPUT, OUTPUT defines for this value +// - This value defaults to input +// - oscFreqOut: If oscio is configured as an output, this will set the output +// frequency +// - This should be a 4-bit value. 0=0%, 0xF=100%, else +// fOSCOut = FOSC / (2^(RegClock[3:0]-1)) +// - This value defaults to 0. +// - oscDivider: Sets the clock divider in REG_MISC. +// - ClkX = fOSC / (2^(RegMisc[6:4] -1)) +// - This value defaults to 1. +// ----------------------------------------------------------------------------- + void configClock(byte oscSource = 2, byte oscPinFunction = 0, + byte oscFreqOut = 0, byte oscDivider = 1); +}; + +#endif // SX1509_library_H diff --git a/sx1509_registers.h b/sx1509_registers.h new file mode 100644 index 00000000..5a1a7ab7 --- /dev/null +++ b/sx1509_registers.h @@ -0,0 +1,152 @@ +/* + sx1509_registers.h + Register definitions for SX1509. + + by: Jim Lindblom + SparkFun Electronics + date: December 13, 2012 + + license: Beerware. Feel free to use it, with or without attribution, in + your own projects. If you find it helpful, buy me a beer next time you + see me at the local pub. +*/ + +#define REG_INPUT_DISABLE_B 0x00 // RegInputDisableB Input buffer disable register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_INPUT_DISABLE_A 0x01 // RegInputDisableA Input buffer disable register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_LONG_SLEW_B 0x02 // RegLongSlewB Output buffer long slew register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_LONG_SLEW_A 0x03 // RegLongSlewA Output buffer long slew register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_LOW_DRIVE_B 0x04 // RegLowDriveB Output buffer low drive register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_LOW_DRIVE_A 0x05 // RegLowDriveA Output buffer low drive register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_PULL_UP_B 0x06 // RegPullUpB Pull_up register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_PULL_UP_A 0x07 // RegPullUpA Pull_up register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_PULL_DOWN_B 0x08 // RegPullDownB Pull_down register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_PULL_DOWN_A 0x09 // RegPullDownA Pull_down register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_OPEN_DRAIN_B 0x0A // RegOpenDrainB Open drain register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_OPEN_DRAIN_A 0x0B // RegOpenDrainA Open drain register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_POLARITY_B 0x0C // RegPolarityB Polarity register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_POLARITY_A 0x0D // RegPolarityA Polarity register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_DIR_B 0x0E // RegDirB Direction register _ I/O[15_8] (Bank B) 1111 1111 +#define REG_DIR_A 0x0F // RegDirA Direction register _ I/O[7_0] (Bank A) 1111 1111 +#define REG_DATA_B 0x10 // RegDataB Data register _ I/O[15_8] (Bank B) 1111 1111* +#define REG_DATA_A 0x11 // RegDataA Data register _ I/O[7_0] (Bank A) 1111 1111* +#define REG_INTERRUPT_MASK_B 0x12 // RegInterruptMaskB Interrupt mask register _ I/O[15_8] (Bank B) 1111 1111 +#define REG_INTERRUPT_MASK_A 0x13 // RegInterruptMaskA Interrupt mask register _ I/O[7_0] (Bank A) 1111 1111 +#define REG_SENSE_HIGH_B 0x14 // RegSenseHighB Sense register for I/O[15:12] 0000 0000 +#define REG_SENSE_LOW_B 0x15 // RegSenseLowB Sense register for I/O[11:8] 0000 0000 +#define REG_SENSE_HIGH_A 0x16 // RegSenseHighA Sense register for I/O[7:4] 0000 0000 +#define REG_SENSE_LOW_A 0x17 // RegSenseLowA Sense register for I/O[3:0] 0000 0000 +#define REG_INTERRUPT_SOURCE_B 0x18 // RegInterruptSourceB Interrupt source register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_INTERRUPT_SOURCE_A 0x19 // RegInterruptSourceA Interrupt source register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_EVENT_STATUS_B 0x1A // RegEventStatusB Event status register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_EVENT_STATUS_A 0x1B // RegEventStatusA Event status register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_LEVEL_SHIFTER_1 0x1C // RegLevelShifter1 Level shifter register 0000 0000 +#define REG_LEVEL_SHIFTER_2 0x1D // RegLevelShifter2 Level shifter register 0000 0000 +#define REG_CLOCK 0x1E // RegClock Clock management register 0000 0000 +#define REG_MISC 0x1F // RegMisc Miscellaneous device settings register 0000 0000 +#define REG_LED_DRIVER_ENABLE_B 0x20 // RegLEDDriverEnableB LED driver enable register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_LED_DRIVER_ENABLE_A 0x21 // RegLEDDriverEnableA LED driver enable register _ I/O[7_0] (Bank A) 0000 0000 +// Debounce and Keypad Engine +#define REG_DEBOUNCE_CONFIG 0x22 // RegDebounceConfig Debounce configuration register 0000 0000 +#define REG_DEBOUNCE_ENABLE_B 0x23 // RegDebounceEnableB Debounce enable register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_DEBOUNCE_ENABLE_A 0x24 // RegDebounceEnableA Debounce enable register _ I/O[7_0] (Bank A) 0000 0000 +#define REG_KEY_CONFIG_1 0x25 // RegKeyConfig1 Key scan configuration register 0000 0000 +#define REG_KEY_CONFIG_2 0x26 // RegKeyConfig2 Key scan configuration register 0000 0000 +#define REG_KEY_DATA_1 0x27 // RegKeyData1 Key value (column) 1111 1111 +#define REG_KEY_DATA_2 0x28 // RegKeyData2 Key value (row) 1111 1111 +// LED Driver (PWM, blinking, breathing) +#define REG_T_ON_0 0x29 // RegTOn0 ON time register for I/O[0] 0000 0000 +#define REG_I_ON_0 0x2A // RegIOn0 ON intensity register for I/O[0] 1111 1111 +#define REG_OFF_0 0x2B // RegOff0 OFF time/intensity register for I/O[0] 0000 0000 +#define REG_T_ON_1 0x2C // RegTOn1 ON time register for I/O[1] 0000 0000 +#define REG_I_ON_1 0x2D // RegIOn1 ON intensity register for I/O[1] 1111 1111 +#define REG_OFF_1 0x2E // RegOff1 OFF time/intensity register for I/O[1] 0000 0000 +#define REG_T_ON_2 0x2F // RegTOn2 ON time register for I/O[2] 0000 0000 +#define REG_I_ON_2 0x30 // RegIOn2 ON intensity register for I/O[2] 1111 1111 +#define REG_OFF_2 0x31 // RegOff2 OFF time/intensity register for I/O[2] 0000 0000 +#define REG_T_ON_3 0x32 // RegTOn3 ON time register for I/O[3] 0000 0000 +#define REG_I_ON_3 0x33 // RegIOn3 ON intensity register for I/O[3] 1111 1111 +#define REG_OFF_3 0x34 // RegOff3 OFF time/intensity register for I/O[3] 0000 0000 +#define REG_T_ON_4 0x35 // RegTOn4 ON time register for I/O[4] 0000 0000 +#define REG_I_ON_4 0x36 // RegIOn4 ON intensity register for I/O[4] 1111 1111 +#define REG_OFF_4 0x37 // RegOff4 OFF time/intensity register for I/O[4] 0000 0000 +#define REG_T_RISE_4 0x38 // RegTRise4 Fade in register for I/O[4] 0000 0000 +#define REG_T_FALL_4 0x39 // RegTFall4 Fade out register for I/O[4] 0000 0000 +#define REG_T_ON_5 0x3A // RegTOn5 ON time register for I/O[5] 0000 0000 +#define REG_I_ON_5 0x3B // RegIOn5 ON intensity register for I/O[5] 1111 1111 +#define REG_OFF_5 0x3C // RegOff5 OFF time/intensity register for I/O[5] 0000 0000 +#define REG_T_RISE_5 0x3D // RegTRise5 Fade in register for I/O[5] 0000 0000 +#define REG_T_FALL_5 0x3E // RegTFall5 Fade out register for I/O[5] 0000 0000 +#define REG_T_ON_6 0x3F // RegTOn6 ON time register for I/O[6] 0000 0000 +#define REG_I_ON_6 0x40 // RegIOn6 ON intensity register for I/O[6] 1111 1111 +#define REG_OFF_6 0x41 // RegOff6 OFF time/intensity register for I/O[6] 0000 0000 +#define REG_T_RISE_6 0x42 // RegTRise6 Fade in register for I/O[6] 0000 0000 +#define REG_T_FALL_6 0x43 // RegTFall6 Fade out register for I/O[6] 0000 0000 +#define REG_T_ON_7 0x44 // RegTOn7 ON time register for I/O[7] 0000 0000 +#define REG_I_ON_7 0x45 // RegIOn7 ON intensity register for I/O[7] 1111 1111 +#define REG_OFF_7 0x46 // RegOff7 OFF time/intensity register for I/O[7] 0000 0000 +#define REG_T_RISE_7 0x47 // RegTRise7 Fade in register for I/O[7] 0000 0000 +#define REG_T_FALL_7 0x48 // RegTFall7 Fade out register for I/O[7] 0000 0000 +#define REG_T_ON_8 0x49 // RegTOn8 ON time register for I/O[8] 0000 0000 +#define REG_I_ON_8 0x4A // RegIOn8 ON intensity register for I/O[8] 1111 1111 +#define REG_OFF_8 0x4B // RegOff8 OFF time/intensity register for I/O[8] 0000 0000 +#define REG_T_ON_9 0x4C // RegTOn9 ON time register for I/O[9] 0000 0000 +#define REG_I_ON_9 0x4D // RegIOn9 ON intensity register for I/O[9] 1111 1111 +#define REG_OFF_9 0x4E // RegOff9 OFF time/intensity register for I/O[9] 0000 0000 +#define REG_T_ON_10 0x4F // RegTOn10 ON time register for I/O[10] 0000 0000 +#define REG_I_ON_10 0x50 // RegIOn10 ON intensity register for I/O[10] 1111 1111 +#define REG_OFF_10 0x51 // RegOff10 OFF time/intensity register for I/O[10] 0000 0000 +#define REG_T_ON_11 0x52 // RegTOn11 ON time register for I/O[11] 0000 0000 +#define REG_I_ON_11 0x53 // RegIOn11 ON intensity register for I/O[11] 1111 1111 +#define REG_OFF_11 0x54 // RegOff11 OFF time/intensity register for I/O[11] 0000 0000 +#define REG_T_ON_12 0x55 // RegTOn12 ON time register for I/O[12] 0000 0000 +#define REG_I_ON_12 0x56 // RegIOn12 ON intensity register for I/O[12] 1111 1111 +#define REG_OFF_12 0x57 // RegOff12 OFF time/intensity register for I/O[12] 0000 0000 +#define REG_T_RISE_12 0x58 // RegTRise12 Fade in register for I/O[12] 0000 0000 +#define REG_T_FALL_12 0x59 // RegTFall12 Fade out register for I/O[12] 0000 0000 +#define REG_T_ON_13 0x5A // RegTOn13 ON time register for I/O[13] 0000 0000 +#define REG_I_ON_13 0x5B // RegIOn13 ON intensity register for I/O[13] 1111 1111 +#define REG_OFF_13 0x5C // RegOff13 OFF time/intensity register for I/O[13] 0000 0000 +#define REG_T_RISE_13 0x5D // RegTRise13 Fade in register for I/O[13] 0000 0000 +#define REG_T_FALL_13 0x5E // RegTFall13 Fade out register for I/O[13] 0000 0000 +#define REG_T_ON_14 0x5F // RegTOn14 ON time register for I/O[14] 0000 0000 +#define REG_I_ON_14 0x60 // RegIOn14 ON intensity register for I/O[14] 1111 1111 +#define REG_OFF_14 0x61 // RegOff14 OFF time/intensity register for I/O[14] 0000 0000 +#define REG_T_RISE_14 0x62 // RegTRise14 Fade in register for I/O[14] 0000 0000 +#define REG_T_FALL_14 0x63 // RegTFall14 Fade out register for I/O[14] 0000 0000 +#define REG_T_ON_15 0x64 // RegTOn15 ON time register for I/O[15] 0000 0000 +#define REG_I_ON_15 0x65 // RegIOn15 ON intensity register for I/O[15] 1111 1111 +#define REG_OFF_15 0x66 // RegOff15 OFF time/intensity register for I/O[15] 0000 0000 +#define REG_T_RISE_15 0x67 // RegTRise15 Fade in register for I/O[15] 0000 0000 +#define REG_T_FALL_15 0x68 // RegTFall15 Fade out register for I/O[15] 0000 0000 +// Miscellaneous +#define REG_HIGH_INPUT_B 0x69 // RegHighInputB High input enable register _ I/O[15_8] (Bank B) 0000 0000 +#define REG_HIGH_INPUT_A 0x6A // RegHighInputA High input enable register _ I/O[7_0] (Bank A) 0000 0000 +// Software Reset +#define REG_RESET 0x7D // RegReset Software reset register 0000 0000 +#define REG_TEST_1 0x7E // RegTest1 Test register 0000 0000 +#define REG_TEST_2 0x7F // RegTest2 Test register 0000 0000 + +byte REG_I_ON[16] = {REG_I_ON_0, REG_I_ON_1, REG_I_ON_2, REG_I_ON_3, + REG_I_ON_4, REG_I_ON_5, REG_I_ON_6, REG_I_ON_7, + REG_I_ON_8, REG_I_ON_9, REG_I_ON_10, REG_I_ON_11, + REG_I_ON_12, REG_I_ON_13, REG_I_ON_14, REG_I_ON_15}; + +byte REG_T_ON[16] = {REG_T_ON_0, REG_T_ON_1, REG_T_ON_2, REG_T_ON_3, + REG_T_ON_4, REG_T_ON_5, REG_T_ON_6, REG_T_ON_7, + REG_T_ON_8, REG_T_ON_9, REG_T_ON_10, REG_T_ON_11, + REG_T_ON_12, REG_T_ON_13, REG_T_ON_14, REG_T_ON_15}; + +byte REG_OFF[16] = {REG_OFF_0, REG_OFF_1, REG_OFF_2, REG_OFF_3, + REG_OFF_4, REG_OFF_5, REG_OFF_6, REG_OFF_7, + REG_OFF_8, REG_OFF_9, REG_OFF_10, REG_OFF_11, + REG_OFF_12, REG_OFF_13, REG_OFF_14, REG_OFF_15}; + +byte REG_T_RISE[16] = {0xFF, 0xFF, 0xFF, 0xFF, + REG_T_RISE_4, REG_T_RISE_5, REG_T_RISE_6, REG_T_RISE_7, + 0xFF, 0xFF, 0xFF, 0xFF, + REG_T_RISE_12, REG_T_RISE_13, REG_T_RISE_14, REG_T_RISE_15}; + +byte REG_T_FALL[16] = {0xFF, 0xFF, 0xFF, 0xFF, + REG_T_FALL_4, REG_T_FALL_5, REG_T_FALL_6, REG_T_FALL_7, + 0xFF, 0xFF, 0xFF, 0xFF, + REG_T_FALL_12, REG_T_FALL_13, REG_T_FALL_14, REG_T_FALL_15};