*lots* of stuff .. :) - got PWM working!
also, i didn't make a note of it in the *.md file, but Waveform Generation Mode 15 for fast PWM wasn't working right (well.. wasn't working how i expected it to). i misinterpreted what the modes were doing, partially (haha, or all-ly?) because i didn't read the description of fast pwm thoroughly enough... in any case, all the information's in the datasheet, and it's actually not terribly long. i'm not sure how to correctly use Mode 15 yet, but i think i'll leave it alone for now, since Mode 5 works as expected, and i think what the datasheet says about *that* makes enough sense to me for me to be content for the moment.partial-rewrite
parent
4dd05f515b
commit
19725eed4a
|
@ -125,6 +125,14 @@
|
|||
(https://github.com/arduino/Arduino/tree/master/libraries/Wire/utility)
|
||||
: (arduino / Arduino / libraries / Wire / utility)
|
||||
|
||||
* forum: [Interfacing MCP23018 io expander via Arduino]
|
||||
(http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282150189)
|
||||
: contains a quick MCP23017 library in C++
|
||||
|
||||
* github: [maniacbug / Arduino / libraries / MCP23018]
|
||||
(https://github.com/maniacbug/Arduino/tree/master/libraries/MCP23018)
|
||||
: library in C++
|
||||
|
||||
* zip: [PJRC: usb_keyboard]
|
||||
(http://pjrc.com/teensy/usb_keyboard.zip)
|
||||
|
||||
|
@ -182,3 +190,9 @@
|
|||
* from [the PJRC website]
|
||||
(http://pjrc.com/teensy/datasheets.html)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Released under The MIT License (MIT) (see "license.md") at
|
||||
<https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
|
|
|
@ -3,3 +3,9 @@
|
|||
[ergodox-firmware]: https://github.com/benblazak/ergodox-firmware
|
||||
[ergodox keyboard]: http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Released under The MIT License (MIT) (see "license.md") at
|
||||
<https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergodox controller (Teensy 2.0 and MCP23018) specific stuff
|
||||
* - public things are prefixed by `controller_` or `CONTROLLER_`
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~ documentation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Pinouts and Pin assignments
|
||||
* - '+' indicates pin
|
||||
* - 'o' indicates unused pin
|
||||
* - '-'s inserted between some of the pin functions for readability
|
||||
* - 'OC**' pins enclosed in parenthesis had lines over them in the pinout
|
||||
* ----------------------------------------------------------------------------
|
||||
* ----------------------------------------------------------------------------
|
||||
* Teensy 2.0
|
||||
* ========== GND +---.....---+ VCC
|
||||
* SS PB0 + + PF0 ADC0
|
||||
* SCLK PB1 + + PF1 ADC1
|
||||
* MOSI PB2 + + PF4 ADC4
|
||||
* MISO PB3 + + + + PF5 ADC5
|
||||
* RTS OC1C OC0A --------- PB7 + PE6 AREF + PF6 ADC6
|
||||
* OC0B INT0 SCL PD0 + AIN0 + PF7 ADC7
|
||||
* INT1 SDA PD1 + INT6 + PB6 ADC13 OC1B OC4B
|
||||
* RXD1 ----------- INT2 --- PD2 + + PB5 ADC12 OC1A (OC4B)
|
||||
* TXD1 ----------- INT3 --- PD3 + + PB4 ADC11
|
||||
* OC3A (OC4A) -------- PC6 + + PD7 ADC10 T0 -- OC4D
|
||||
* ICP3 ----- OC4A --------- PC7 +-+-+-+-+-+-+ PD6 ADC9 T1 - (OC4D) onboardLED
|
||||
* CTS XCK1 PD5 --/ | | | \-- PD4 ADC8 ------------ ICP1
|
||||
* VCC ------------------/ | \-------------- RST
|
||||
* GND --------------------/
|
||||
* ----------------------------------------------------------------------------
|
||||
* MCP23018
|
||||
* ======== Vss(GND) +01---.---28+ NC
|
||||
* NC +02 27+ GPA7
|
||||
* GPB0 +03 26+ GPA6
|
||||
* GPB1 +04 25+ GPA5
|
||||
* GPB2 +05 24+ GPA4
|
||||
* GPB3 +06 23+ GPA3
|
||||
* GPB4 +07 22+ GPA2
|
||||
* GPB5 +08 21+ GPA1
|
||||
* GPB6 +09 20+ GPA0
|
||||
* GPB7 +10 19+ INTA
|
||||
* Vdd(Vcc) +11 18+ INTB
|
||||
* SCL +12 17+ NC
|
||||
* SDA +13 16+ RESET
|
||||
* NC +14-------15+ ADDR
|
||||
* ----------------------------------------------------------------------------
|
||||
* ----------------------------------------------------------------------------
|
||||
* Teensy 2.0 Pin Assignments
|
||||
* ==========================
|
||||
* power_negative GND +---.....---+ Vcc power_positive
|
||||
* column6 PB0 + + PF0 row6
|
||||
* o + PF1 row7
|
||||
* o + PF4 row8
|
||||
* o o o + PF5 row9
|
||||
* LED3 OC1C + + PF6 rowA
|
||||
* I2C SCL + + PF7 rowB
|
||||
* I2C SDA + + OC1B LED2
|
||||
* column3 PD2 + + OC1A LED1
|
||||
* column4 PD3 + + PB4 column0
|
||||
* column1 PC6 + + PD7 column5
|
||||
* column2 PC7 +-o-o-o-o-o-o
|
||||
*
|
||||
* notes:
|
||||
* - SCL and SDA: Need external pull-up resistors. Sometimes the internal
|
||||
* pull-ups are enough (see datasheet section 20.5.1), but i think for this
|
||||
* project we'll want external ones, in case people want to separate the
|
||||
* halves very far.
|
||||
* ----------------------------------------------------------------------------
|
||||
* MCP32018 Pin Assignments
|
||||
* ========================
|
||||
* power_negative Vss(GND) +01---.---28o
|
||||
* o02 27o
|
||||
* column0 GPB0 +03 26o
|
||||
* column1 GPB1 +04 25+ GPA5 rowB
|
||||
* column2 GPB2 +05 24+ GPA4 rowA
|
||||
* column3 GPB3 +06 23+ GPA3 row9
|
||||
* column4 GPB4 +07 22+ GPA2 row8
|
||||
* column5 GPB5 +08 21+ GPA1 row7
|
||||
* column6 GPB6 +09 20+ GPA0 row6
|
||||
* o10 19o
|
||||
* power_positive Vdd(Vcc) +11 18o
|
||||
* I2C SCL +12 17o
|
||||
* I2C SDA +13 16o
|
||||
* o14-------15+ ADDR (see note)
|
||||
*
|
||||
* notes:
|
||||
* - ADDR (pin15): Set slave address to 0b0100000 by connecting to Vss(GND).
|
||||
* (The user-defined bits are the three least significant).
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Notes about Registers
|
||||
* ----------------------------------------------------------------------------
|
||||
* General I/O (see datasheet section 10.2.1)
|
||||
*
|
||||
* DDRxn function PINxn function
|
||||
* 1 output 1 drive high
|
||||
* 0 drive low
|
||||
* 0 input 1 internal pull-up on
|
||||
* 0 internal pull-up off
|
||||
*
|
||||
* notes:
|
||||
* - Unused pins should be set as input with internal pullup enabled (see
|
||||
* datasheet section 10.2.6).
|
||||
* ----------------------------------------------------------------------------
|
||||
* PWM on ports OC1(A|B|C) (see datasheet section 14.10)
|
||||
*
|
||||
* notes:
|
||||
* - PWM pins should be set as outputs.
|
||||
* - we want Waveform Generation Mode 15
|
||||
* (fast PWM, TOP = OCRnA)
|
||||
* (see table 14-5)
|
||||
* - set (TCCRB[4,3],TCCRA[1,0]) to (1,1,1,1)
|
||||
* - we want "Compare Output Mode, Fast PWM" to be 0b10
|
||||
* "Clear OCnA/OCnB/OCnC on compare match, set OCnA/OCnB/OCnC at TOP"
|
||||
* (see table 14-3)
|
||||
* this way higher values of OCR1(A|B|C) will mean longer 'on' times for the
|
||||
* LEDs
|
||||
* - when in a fast PWM mode, set (TCCR1A[7,6,5,4,3,2]) to (1,0,1,0,1,0)
|
||||
* - we want "Clock Select Bit Description" to be 0b001
|
||||
* "clkI/O/1 (No prescaling)"
|
||||
* (see table 14-6)
|
||||
* - set (TCCR1B[2,1,0]) to (0,0,1)
|
||||
* - LEDs will be at minimum brightness until OCR1(A|B|C) are changed (since
|
||||
* the default value of all the bits in those registers is 0)
|
||||
*
|
||||
* abbreviations:
|
||||
* - OCR = Output Compare Register
|
||||
* - TCCR = Timer/Counter Control Register
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "lib/twi.h"
|
||||
|
||||
#include "teensy-2-0--mcp23018.h"
|
||||
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~ macros ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define CPU_16MHz 0x00
|
||||
#define CPU_8MHz 0x01
|
||||
#define CPU_4MHz 0x02
|
||||
#define CPU_2MHz 0x03
|
||||
#define CPU_1MHz 0x04
|
||||
#define CPU_500kHz 0x05
|
||||
#define CPU_250kHz 0x06
|
||||
#define CPU_125kHz 0x07
|
||||
#define CPU_62kHz 0x08
|
||||
|
||||
// TWI frequency
|
||||
#define TWI_FREQ 400000 // (see lib/twi.(h|c))
|
||||
|
||||
// pins
|
||||
// --- rows ?TODO
|
||||
// --- columns ?TODO
|
||||
|
||||
|
||||
// mcp23018 pins
|
||||
// TODO
|
||||
// I2C SCL
|
||||
// I2C SDA
|
||||
// ROW_6 GPA0
|
||||
// ROW_7 GPA1
|
||||
// ROW_8 GPA2
|
||||
// ROW_9 GPA3
|
||||
// ROW_A GPA4
|
||||
// ROW_B GPA5
|
||||
// COLUMN_0_LH GPB0
|
||||
// COLUMN_1_LH GPB1
|
||||
// COLUMN_2_LH GPB2
|
||||
// COLUMN_3_LH GPB3
|
||||
// COLUMN_4_LH GPB4
|
||||
// COLUMN_5_LH GPB5
|
||||
// COLUMN_6_LH GPB6
|
||||
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~ functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void controller_init() {
|
||||
teensy_init(); // must be first
|
||||
mcp23018_init(); // must be second
|
||||
}
|
||||
|
||||
void teensy_init() {
|
||||
CPU_PRESCALE(CPU_16MHz); // speed should match F_CPU in makefile
|
||||
|
||||
// unused pins
|
||||
DDRB &= ~0b00001110; // set B(1,2,3) as input
|
||||
PORTB |= 0b00001110; // set B(1,2,3) internal pull-up enabled
|
||||
DDRD &= ~0b01110000; // set D(4,5,6) as input
|
||||
PORTD |= 0b01110000; // set D(4,5,6) internal pull-up enabled
|
||||
DDRE &= ~0b01000000; // set E(6) as input
|
||||
PORTE |= 0b01000000; // set E(6) internal pull-up enabled
|
||||
|
||||
// LEDs
|
||||
DDRB |= 0b11100000; // set B(5,6,7) as output
|
||||
TCCR1A = 0b10101011; // set and configure fast PWM
|
||||
TCCR1B = 0b00011001; // set and configure fast PWM
|
||||
|
||||
// rows
|
||||
DDRF |= 0b11110011; // set F(0,1,4,5,6,7) as output
|
||||
PORTF |= 0b11110011; // set F(0,1,4,5,6,7) drive high
|
||||
|
||||
// columns
|
||||
DDRB &= ~0b00010001; // set B(0,4) as input
|
||||
PORTB |= 0b00010001; // set B(0,4) internal pull-up enabled
|
||||
DDRC &= ~0b11000000; // set C(6,7) as input
|
||||
PORTC |= 0b11000000; // set C(6,7) internal pull-up enabled
|
||||
DDRD &= ~0b10001100; // set D(2,3,7) as input
|
||||
PORTD |= 0b10001100; // set D(2,3,7) internal pull-up enabled
|
||||
|
||||
// I2C (TWI)
|
||||
twi_init(); // (on pins D(0,1))
|
||||
twi_setAddress(0b0100000);
|
||||
}
|
||||
|
||||
// TODO
|
||||
void mcp23018_init() {
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergodox controller (Teensy 2.0 and MCP23018) specific stuff
|
||||
* - public things are prefixed by `controller_` or `CONTROLLER_`
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// LEDs
|
||||
#define CONTROLLER_LED1_ON (OCR1A = 0xFFFF)
|
||||
#define CONTROLLER_LED1_OFF (OCR1A = 0x0000)
|
||||
#define CONTROLLER_LED1_SET(n) (OCR1A = (uint16_t)(n))
|
||||
#define CONTROLLER_LED1_SET_PERCENT(n) (OCR1A = (uint16_t)((n) * 0xFFFF))
|
||||
#define CONTROLLER_LED2_ON (OCR1B = 0xFFFF)
|
||||
#define CONTROLLER_LED2_OFF (OCR1B = 0x0000)
|
||||
#define CONTROLLER_LED2_SET(n) (OCR1B = (uint16_t)(n))
|
||||
#define CONTROLLER_LED2_SET_PERCENT(n) (OCR1B = (uint16_t)((n) * 0xFFFF))
|
||||
#define CONTROLLER_LED3_ON (OCR1C = 0xFFFF)
|
||||
#define CONTROLLER_LED3_OFF (OCR1C = 0x0000)
|
||||
#define CONTROLLER_LED3_SET(n) (OCR1C = (uint16_t)(n))
|
||||
#define CONTROLLER_LED3_SET_PERCENT(n) (OCR1C = (uint16_t)((n) * 0xFFFF))
|
||||
|
||||
|
||||
// init
|
||||
void controller_init();
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Firmware for the ergoDOX keyboard
|
||||
* Firmware main file
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
|
@ -7,13 +7,13 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "lib/print.h"
|
||||
#include "lib/pjrc/print.h"
|
||||
|
||||
#include "keyboard.h"
|
||||
|
||||
|
||||
void main() {
|
||||
init();
|
||||
}
|
||||
|
||||
void init() {
|
||||
}
|
||||
// TODO
|
||||
// int main(void) {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Keyboard specific stuff
|
||||
* - public things are prefixed by `kb_` or `KB_`
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// TODO
|
||||
|
|
@ -36,67 +36,47 @@
|
|||
#include "layout.h"
|
||||
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~ macros ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
// TODO
|
||||
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~ variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
uint8_t kb_is_pressed[KB_ROWS][KB_COLUMNS] = {
|
||||
// uint8_t kb_is_pressed[KB_ROWS][KB_COLUMNS] = {
|
||||
// --- right hand ---
|
||||
// column 0 1 2 3 4 5 6
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x0
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x1
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x2
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x3
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x4
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x5
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x0
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x1
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x2
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x3
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x4
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x5
|
||||
// --- left hand ---
|
||||
// column 0 1 2 3 4 5 6
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x6
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x7
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x8
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x9
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0xA
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0xB
|
||||
}
|
||||
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x6
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x7
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x8
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x9
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0xA
|
||||
// 0, 0, 0, 0, 0, 0, 0 //row 0xB
|
||||
// };
|
||||
//
|
||||
// TODO: this belongs in program space
|
||||
uint8_t kb_maps[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
// uint8_t layout_layers[LAYOUT_LAYERS][LAYOUT_ROWS][LAYOUT_COLUMNS] = {
|
||||
// ------- layer: default -------
|
||||
// --- right hand ---
|
||||
// column 0 1 2 3 4 5 6
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x0
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x1
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x2
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x3
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x4
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x5
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x0
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x1
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x2
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x3
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x4
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x5
|
||||
// --- left hand ---
|
||||
// column 0 1 2 3 4 5 6
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x6
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x7
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x8
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0x9
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0xA
|
||||
0, 0, 0, 0, 0, 0, 0, //row 0xB
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~ functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
// TODO
|
||||
void kb_init() {
|
||||
}
|
||||
|
||||
// TODO
|
||||
// - cycle through row=HIGH and read each column
|
||||
void kb_update() {
|
||||
}
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x6
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x7
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x8
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0x9
|
||||
// 0, 0, 0, 0, 0, 0, 0, //row 0xA
|
||||
// 0, 0, 0, 0, 0, 0, 0 //row 0xB
|
||||
// };
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout specific stuff
|
||||
* - public things are prefixed by `layout_` or `LAYOUT_`
|
||||
* see "default.c"
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
|
@ -8,9 +7,9 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#define KB_LAYERS 1
|
||||
#define KB_ROWS 12 // must match real life
|
||||
#define KB_COLUMNS 7 // must match real life
|
||||
#define LAYOUT_LAYERS 1
|
||||
#define LAYOUT_ROWS 12 // must match real life
|
||||
#define LAYOUT_COLUMNS 7 // must match real life
|
||||
|
||||
|
||||
// TODO
|
|
@ -0,0 +1,25 @@
|
|||
#include <util/delay.h>
|
||||
#include "teensy-2-0.h"
|
||||
|
||||
int main(void) {
|
||||
teensy_init();
|
||||
|
||||
TEENSY_LED1_ON;
|
||||
TEENSY_LED2_ON;
|
||||
TEENSY_LED3_ON;
|
||||
|
||||
for(uint8_t i=0;;i++) {
|
||||
TEENSY_LED1_SET( (i+(3*0xFF/2/3)) % 0xFF/2 );
|
||||
TEENSY_LED2_SET( (i+(2*0xFF/2/3)) % 0xFF/2 );
|
||||
TEENSY_LED3_SET( (i+(1*0xFF/2/3)) % 0xFF/2 );
|
||||
|
||||
// counting_up
|
||||
// ? (i == 0xFF ? counting_up = 0 : i++)
|
||||
// : (i == 0x00 ? counting_up = 1 : i--);
|
||||
|
||||
_delay_ms(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: MCP23018 specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#define TWI_ADDRESS MCP23018_TWI_ADDRESS // from header file
|
||||
|
||||
#define True ((uint8_t)1)
|
||||
#define False ((uint8_t)0)
|
||||
|
||||
// register addresses (see "mcp23018.md")
|
||||
#define IODIRA 0x00 // i/o direction register
|
||||
#define IODIRB 0x01
|
||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||
#define GPPUB 0x0D
|
||||
#define GPIOA 0x12 // general purpose i/o port register
|
||||
#define GPIOB 0x13
|
||||
#define OLATA 0x14 // output latch register
|
||||
#define OLATB 0x15
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#include "lib/arduino/twi.h"
|
||||
|
||||
#include "mcp23018.h"
|
||||
|
||||
|
||||
void mcp23018_init(void) {
|
||||
uint8_t data[3];
|
||||
|
||||
// set pin direction
|
||||
// - unused : input : 1
|
||||
// - rows : output : 0
|
||||
// - columns : input : 1
|
||||
data[0] = IODIRA; // start register address
|
||||
data[1] = 0b11000000; // IODIRA
|
||||
data[2] = 0b11111111; // IODIRB
|
||||
twi_writeTo(TWI_ADDRESS, data, 3, True);
|
||||
|
||||
// set pull-up
|
||||
// - unused : on : 1
|
||||
// - rows : off : 0
|
||||
// - columns : on : 1
|
||||
data[0] = GPPUA; // start register address
|
||||
data[1] = 0b11000000; // GPPUA
|
||||
data[2] = 0b11111111; // GPPUB
|
||||
twi_writeTo(TWI_ADDRESS, data, 3, True);
|
||||
|
||||
// set output pins high
|
||||
// - rows : high : 1
|
||||
// - other : low : 0 (or ignored)
|
||||
data[0] = OLATA; // start register address
|
||||
data[1] = 0b00111111; // OLATA
|
||||
twi_writeTo(TWI_ADDRESS, data, 2, True);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: MCP23018 specific exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef MCP23018_h
|
||||
#define MCP23018_h
|
||||
|
||||
|
||||
#define MCP23018_TWI_ADDRESS 0b0100000
|
||||
|
||||
|
||||
void mcp23018_init(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
# Documentation : MCP23018
|
||||
|
||||
## Pinouts and Pin assignments
|
||||
|
||||
* `+` indicates pin
|
||||
* `o` indicates unused pin
|
||||
* `-`s inserted between some of the pin functions for readability
|
||||
* `OC**` pins enclosed in parenthesis had lines over them in the pinout
|
||||
|
||||
### MCP23018
|
||||
Vss(GND) +01---.---28+ NC
|
||||
NC +02 27+ GPA7
|
||||
GPB0 +03 26+ GPA6
|
||||
GPB1 +04 25+ GPA5
|
||||
GPB2 +05 24+ GPA4
|
||||
GPB3 +06 23+ GPA3
|
||||
GPB4 +07 22+ GPA2
|
||||
GPB5 +08 21+ GPA1
|
||||
GPB6 +09 20+ GPA0
|
||||
GPB7 +10 19+ INTA
|
||||
Vdd(Vcc) +11 18+ INTB
|
||||
SCL +12 17+ NC
|
||||
SDA +13 16+ RESET
|
||||
NC +14-------15+ ADDR
|
||||
|
||||
### MCP32018 Pin Assignments
|
||||
|
||||
power_negative Vss(GND) +01---.---28o
|
||||
o02 27o
|
||||
column0 GPB0 +03 26o
|
||||
column1 GPB1 +04 25+ GPA5 rowB
|
||||
column2 GPB2 +05 24+ GPA4 rowA
|
||||
column3 GPB3 +06 23+ GPA3 row9
|
||||
column4 GPB4 +07 22+ GPA2 row8
|
||||
column5 GPB5 +08 21+ GPA1 row7
|
||||
column6 GPB6 +09 20+ GPA0 row6
|
||||
o10 19o
|
||||
power_positive Vdd(Vcc) +11 18o
|
||||
I2C SCL +12 17o
|
||||
I2C SDA +13 16o
|
||||
o14-------15+ ADDR (see note)
|
||||
|
||||
* notes:
|
||||
* ADDR (pin15): Set slave address to `0b0100000` by connecting to Vss(GND).
|
||||
(The user-defined bits are the three least significant).
|
||||
|
||||
## Notes about Registers
|
||||
|
||||
register address function (for all bits)
|
||||
-------- ------- -----------------------
|
||||
IODIRA 0x00 \ 1: set corresponding pin as input
|
||||
IODIRB 0x01 / 0: set ................. as output
|
||||
GPPUA 0x0C \ 1: set corresponding pin internal pull-up on
|
||||
GPPUB 0x0D / 0: set .......................... pull-up off
|
||||
GPIOA 0x12 \ read: returns the value on the port
|
||||
GPIOB 0x13 / write: modifies the OLAT register
|
||||
OLATA 0x14 \ read: returns the value of this register
|
||||
OLATB 0x15 / write: modifies the output latches that control the
|
||||
pins configured as output
|
||||
|
||||
* IOCON (see datasheet section 1.6, table 1-5, register 1-8)
|
||||
* BANK: bit 7; read/write; default = 0
|
||||
* 1: The registers associated with each port are separated into different
|
||||
banks
|
||||
* 0: The registers are in the same bank (addresses are sequential)
|
||||
* SEQOP: bit 5; read/write; default = 0
|
||||
* 1: Sequential operation disabled, address pointer does not increment
|
||||
* 0: Sequential operation enabled, address pointer increments
|
||||
|
||||
* notes:
|
||||
* All addresses given for IOCON.BANK = 0, since that's the default value of
|
||||
the bit, and that's what we'll be using.
|
||||
|
||||
* abbreviations:
|
||||
* IODIR = I/O Direction Register
|
||||
* IOCON = I/O Control Register
|
||||
* GPPU = GPIO Pull-Up Resistor Register
|
||||
* GPIO = General Purpose I/O Port Register
|
||||
* OLAT = Output Latch Register
|
||||
|
||||
## I²C Device Protocol (see datasheet section 1.3, figure 1-1)
|
||||
|
||||
S : Start OP : Device opcode
|
||||
SR : Restart ADDR : Device address
|
||||
P : Stop Dout : Data out from MCP23018
|
||||
W : Write Din : Data in to MCP23018
|
||||
R : Read
|
||||
|
||||
|
||||
S OP W ADDR ----> Din ... Din --> P
|
||||
|
|
||||
|--> SR OP R Dout ... Dout ---> P
|
||||
|<-------------------------|
|
||||
|
|
||||
|--> SR OP W ADDR ... Din --> P
|
||||
|
|
||||
|--> P
|
||||
|
||||
S OP R ----> Dout ... Dout --> P
|
||||
|
|
||||
|--> SR OP R Dout ... Dout ---> P
|
||||
|<--------------------------|
|
||||
|
|
||||
|--> SR OP W ADDR Din ... Din --> P
|
||||
|
|
||||
|--> P
|
||||
|
||||
Byte and Sequential Write
|
||||
-------------------------
|
||||
Byte : S OP W ADDR --> Din --> P
|
||||
Sequential : S OP W ADDR --> Din ... Din --> P
|
||||
|
||||
Byte and Sequential Read
|
||||
------------------------
|
||||
Byte : S OP W ADDR --> SR OP R Dout --> P
|
||||
Sequential : S OP W ADDR --> SR OP R Dout ... Dout --> P
|
||||
|
||||
* notes:
|
||||
* We'll be using sequential mode (ICON.SEQOP = 0; default) (see datasheet
|
||||
section 1.3.1).
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Released under The MIT License (MIT) (see "license.md") at
|
||||
<https://github.com/benblazak/ergodox-firmware>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: Teensy 2.0 specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define CPU_16MHz 0x00
|
||||
#define CPU_8MHz 0x01
|
||||
#define CPU_4MHz 0x02
|
||||
#define CPU_2MHz 0x03
|
||||
#define CPU_1MHz 0x04
|
||||
#define CPU_500kHz 0x05
|
||||
#define CPU_250kHz 0x06
|
||||
#define CPU_125kHz 0x07
|
||||
#define CPU_62kHz 0x08
|
||||
|
||||
// TWI
|
||||
#define TWI_FREQ 400000 // (see "lib/twi.(h|c)")
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "lib/arduino/twi.h"
|
||||
|
||||
#include "teensy-2-0.h"
|
||||
|
||||
|
||||
void teensy_init(void) {
|
||||
CPU_PRESCALE(CPU_16MHz); // speed should match F_CPU in makefile
|
||||
|
||||
// unused pins
|
||||
DDRB &= ~0b00001110; // set B(1,2,3) as input
|
||||
PORTB |= 0b00001110; // set B(1,2,3) internal pull-up enabled
|
||||
DDRD &= ~0b01110000; // set D(4,5,6) as input
|
||||
PORTD |= 0b01110000; // set D(4,5,6) internal pull-up enabled
|
||||
DDRE &= ~0b01000000; // set E(6) as input
|
||||
PORTE |= 0b01000000; // set E(6) internal pull-up enabled
|
||||
|
||||
// LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
|
||||
DDRB |= 0b11100000; // set B(5,6,7) as output
|
||||
TCCR1A = 0b10101001; // set and configure fast PWM
|
||||
TCCR1B = 0b00001001; // set and configure fast PWM
|
||||
|
||||
// rows
|
||||
DDRF |= 0b11110011; // set F(0,1,4,5,6,7) as output
|
||||
PORTF |= 0b11110011; // set F(0,1,4,5,6,7) drive high
|
||||
|
||||
// columns
|
||||
DDRB &= ~0b00010001; // set B(0,4) as input
|
||||
PORTB |= 0b00010001; // set B(0,4) internal pull-up enabled
|
||||
DDRC &= ~0b11000000; // set C(6,7) as input
|
||||
PORTC |= 0b11000000; // set C(6,7) internal pull-up enabled
|
||||
DDRD &= ~0b10001100; // set D(2,3,7) as input
|
||||
PORTD |= 0b10001100; // set D(2,3,7) internal pull-up enabled
|
||||
|
||||
// I2C (TWI)
|
||||
twi_init(); // (on pins D(0,1))
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: Teensy 2.0 specific exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <avr/io.h> // for the register macros
|
||||
|
||||
|
||||
#ifndef TEENSY_2_0_h
|
||||
#define TEENSY_2_0_h
|
||||
|
||||
|
||||
// LED control
|
||||
#define TEENSY_LED1_ON (OCR1A = 0xFF)
|
||||
#define TEENSY_LED1_OFF (OCR1A = 0x00)
|
||||
#define TEENSY_LED1_SET(n) (OCR1A = (uint8_t)(n))
|
||||
#define TEENSY_LED1_SET_PERCENT(n) (OCR1A = (uint8_t)((n) * 0xFF))
|
||||
#define TEENSY_LED2_ON (OCR1B = 0xFF)
|
||||
#define TEENSY_LED2_OFF (OCR1B = 0x00)
|
||||
#define TEENSY_LED2_SET(n) (OCR1B = (uint8_t)(n))
|
||||
#define TEENSY_LED2_SET_PERCENT(n) (OCR1B = (uint8_t)((n) * 0xFF))
|
||||
#define TEENSY_LED3_ON (OCR1C = 0xFF)
|
||||
#define TEENSY_LED3_OFF (OCR1C = 0x00)
|
||||
#define TEENSY_LED3_SET(n) (OCR1C = (uint8_t)(n))
|
||||
#define TEENSY_LED3_SET_PERCENT(n) (OCR1C = (uint8_t)((n) * 0xFF))
|
||||
|
||||
|
||||
void teensy_init(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
# Documentation : Teensy 2.0
|
||||
|
||||
## Pinouts and Pin assignments
|
||||
|
||||
* `+` indicates pin
|
||||
* `o` indicates unused pin
|
||||
* `-`s inserted between some of the pin functions for readability
|
||||
* `OC**` pins enclosed in parenthesis had lines over them in the pinout
|
||||
|
||||
### Teensy 2.0
|
||||
|
||||
GND +---.....---+ VCC
|
||||
SS PB0 + + PF0 ADC0
|
||||
SCLK PB1 + + PF1 ADC1
|
||||
MOSI PB2 + + PF4 ADC4
|
||||
MISO PB3 + + + + PF5 ADC5
|
||||
RTS OC1C OC0A --------- PB7 + PE6 AREF + PF6 ADC6
|
||||
OC0B INT0 SCL PD0 + AIN0 + PF7 ADC7
|
||||
INT1 SDA PD1 + INT6 + PB6 ADC13 OC1B OC4B
|
||||
RXD1 ----------- INT2 --- PD2 + + PB5 ADC12 OC1A (OC4B)
|
||||
TXD1 ----------- INT3 --- PD3 + + PB4 ADC11
|
||||
OC3A (OC4A) -------- PC6 + + PD7 ADC10 T0 -- OC4D
|
||||
ICP3 ----- OC4A --------- PC7 +-+-+-+-+-+-+ PD6 ADC9 T1 - (OC4D) onboardLED
|
||||
CTS XCK1 PD5 --/ | | | \-- PD4 ADC8 ------------ ICP1
|
||||
VCC ------------------/ | \-------------- RST
|
||||
GND --------------------/
|
||||
|
||||
### Teensy 2.0 Pin Assignments
|
||||
|
||||
power_negative GND +---.....---+ Vcc power_positive
|
||||
column6 PB0 + + PF0 row6
|
||||
o + PF1 row7
|
||||
o + PF4 row8
|
||||
o o o + PF5 row9
|
||||
LED3 OC1C + + PF6 rowA
|
||||
I2C SCL + + PF7 rowB
|
||||
I2C SDA + + OC1B LED2
|
||||
column3 PD2 + + OC1A LED1
|
||||
column4 PD3 + + PB4 column0
|
||||
column1 PC6 + + PD7 column5
|
||||
column2 PC7 +-o-o-o-o-o-o
|
||||
|
||||
* notes:
|
||||
* SCL and SDA: Need external pull-up resistors. Sometimes the internal
|
||||
pull-ups are enough (see datasheet section 20.5.1), but i think for this
|
||||
project we'll want external ones, in case people want to separate the
|
||||
halves very far.
|
||||
|
||||
## Notes about Registers
|
||||
|
||||
### General I/O (see datasheet section 10.2.1)
|
||||
|
||||
DDRxn function PORTxn function
|
||||
1 output 1 drive high
|
||||
0 drive low
|
||||
0 input 1 internal pull-up on
|
||||
0 internal pull-up off
|
||||
|
||||
PINxn action function
|
||||
write 1 toggles the value of PORTxn
|
||||
read returns the logical value (1|0) of the pin
|
||||
|
||||
* notes:
|
||||
* Unused pins should be set as input with internal pullup enabled (see
|
||||
datasheet section 10.2.6).
|
||||
* We want the row pins 'drive high' initially, and the column pins set as
|
||||
input with internal pull-up. We'll cycle through driving the row pins low,
|
||||
and checking the column pins in the update function.
|
||||
|
||||
### PWM on ports OC1(A|B|C) (see datasheet section 14.10)
|
||||
|
||||
* notes:
|
||||
* PWM pins should be set as outputs.
|
||||
* we want Waveform Generation Mode 5
|
||||
(fast PWM, 8-bit)
|
||||
(see table 14-5)
|
||||
* set `TCCRB[4,3],TCCRA[1,0]` to `0,1,0,1`
|
||||
* we want "Compare Output Mode, Fast PWM" to be `0b10`
|
||||
"Clear OCnA/OCnB/OCnC on compare match, set OCnA/OCnB/OCnC at TOP"
|
||||
(see table 14-3)
|
||||
this way higher values of `OCR1(A|B|C)` will mean longer 'on' times for the
|
||||
LEDs
|
||||
* when in a fast PWM mode, set `TCCR1A[7,6,5,4,3,2]` to `1,0,1,0,1,0`
|
||||
* we want "Clock Select Bit Description" to be `0b001`
|
||||
"clkI/O/1 (No prescaling)"
|
||||
(see table 14-6)
|
||||
* set `TCCR1B[2,1,0]` to `0,0,1`
|
||||
* LEDs will be at minimum brightness until OCR1(A|B|C) are changed (since
|
||||
the default value of all the bits in those registers is 0)
|
||||
|
||||
* abbreviations:
|
||||
* OCR = Output Compare Register
|
||||
* TCCR = Timer/Counter Control Register
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Released under The MIT License (MIT) (see "license.md") at
|
||||
<https://github.com/benblazak/ergodox-firmware>
|
||||
|
|
@ -15,8 +15,6 @@
|
|||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
@ -25,7 +23,6 @@
|
|||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <compat/twi.h>
|
||||
#include "Arduino.h" // for digitalWrite
|
||||
|
||||
#ifndef cbi
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
|
@ -35,20 +32,17 @@
|
|||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||
#endif
|
||||
|
||||
#include "pins_arduino.h"
|
||||
#include "twi.h"
|
||||
|
||||
static volatile uint8_t twi_state;
|
||||
static volatile uint8_t twi_slarw;
|
||||
static volatile uint8_t twi_sendStop; // should the transaction end with a stop
|
||||
static volatile uint8_t twi_inRepStart; // in the middle of a repeated start
|
||||
static uint8_t twi_slarw;
|
||||
|
||||
static void (*twi_onSlaveTransmit)(void);
|
||||
static void (*twi_onSlaveReceive)(uint8_t*, int);
|
||||
|
||||
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
|
||||
static volatile uint8_t twi_masterBufferIndex;
|
||||
static volatile uint8_t twi_masterBufferLength;
|
||||
static uint8_t twi_masterBufferLength;
|
||||
|
||||
static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
|
||||
static volatile uint8_t twi_txBufferIndex;
|
||||
|
@ -69,17 +63,23 @@ void twi_init(void)
|
|||
{
|
||||
// initialize state
|
||||
twi_state = TWI_READY;
|
||||
twi_sendStop = true; // default value
|
||||
twi_inRepStart = false;
|
||||
|
||||
// activate internal pullups for twi.
|
||||
digitalWrite(SDA, 1);
|
||||
digitalWrite(SCL, 1);
|
||||
|
||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
|
||||
// activate internal pull-ups for twi
|
||||
// as per note from atmega8 manual pg167
|
||||
sbi(PORTC, 4);
|
||||
sbi(PORTC, 5);
|
||||
#else
|
||||
// activate internal pull-ups for twi
|
||||
// as per note from atmega128 manual pg204
|
||||
sbi(PORTD, 0);
|
||||
sbi(PORTD, 1);
|
||||
#endif
|
||||
|
||||
// initialize twi prescaler and bit rate
|
||||
cbi(TWSR, TWPS0);
|
||||
cbi(TWSR, TWPS1);
|
||||
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
|
||||
TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2;
|
||||
|
||||
/* twi bit rate formula from atmega128 manual pg 204
|
||||
SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
|
||||
|
@ -109,10 +109,9 @@ void twi_setAddress(uint8_t address)
|
|||
* Input address: 7bit i2c device address
|
||||
* data: pointer to byte array
|
||||
* length: number of bytes to read into array
|
||||
* sendStop: Boolean indicating whether to send a stop at the end
|
||||
* Output number of bytes read
|
||||
*/
|
||||
uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop)
|
||||
uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
|
@ -126,7 +125,6 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
|
|||
continue;
|
||||
}
|
||||
twi_state = TWI_MRX;
|
||||
twi_sendStop = sendStop;
|
||||
// reset error state (0xFF.. no error occured)
|
||||
twi_error = 0xFF;
|
||||
|
||||
|
@ -143,20 +141,8 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
|
|||
twi_slarw = TW_READ;
|
||||
twi_slarw |= address << 1;
|
||||
|
||||
if (true == twi_inRepStart) {
|
||||
// if we're in the repeated start state, then we've already sent the start,
|
||||
// (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
|
||||
// We need to remove ourselves from the repeated start state before we enable interrupts,
|
||||
// since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
|
||||
// up. Also, don't enable the START interrupt. There may be one pending from the
|
||||
// repeated start that we sent outselves, and that would really confuse things.
|
||||
twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR
|
||||
TWDR = twi_slarw;
|
||||
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
|
||||
}
|
||||
else
|
||||
// send start condition
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
|
||||
// send start condition
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
|
||||
|
||||
// wait for read operation to complete
|
||||
while(TWI_MRX == twi_state){
|
||||
|
@ -182,14 +168,13 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
|
|||
* data: pointer to byte array
|
||||
* length: number of bytes in array
|
||||
* wait: boolean indicating to wait for write or not
|
||||
* sendStop: boolean indicating whether or not to send a stop at the end
|
||||
* Output 0 .. success
|
||||
* 1 .. length to long for buffer
|
||||
* 2 .. address send, NACK received
|
||||
* 3 .. data send, NACK received
|
||||
* 4 .. other twi error (lost bus arbitration, bus error, ..)
|
||||
*/
|
||||
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
|
||||
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
|
@ -203,7 +188,6 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
|
|||
continue;
|
||||
}
|
||||
twi_state = TWI_MTX;
|
||||
twi_sendStop = sendStop;
|
||||
// reset error state (0xFF.. no error occured)
|
||||
twi_error = 0xFF;
|
||||
|
||||
|
@ -220,23 +204,8 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
|
|||
twi_slarw = TW_WRITE;
|
||||
twi_slarw |= address << 1;
|
||||
|
||||
// if we're in a repeated start, then we've already sent the START
|
||||
// in the ISR. Don't do it again.
|
||||
//
|
||||
if (true == twi_inRepStart) {
|
||||
// if we're in the repeated start state, then we've already sent the start,
|
||||
// (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
|
||||
// We need to remove ourselves from the repeated start state before we enable interrupts,
|
||||
// since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
|
||||
// up. Also, don't enable the START interrupt. There may be one pending from the
|
||||
// repeated start that we sent outselves, and that would really confuse things.
|
||||
twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR
|
||||
TWDR = twi_slarw;
|
||||
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
|
||||
}
|
||||
else
|
||||
// send start condition
|
||||
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
|
||||
// send start condition
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
|
||||
|
||||
// wait for write operation to complete
|
||||
while(wait && (TWI_MTX == twi_state)){
|
||||
|
@ -263,7 +232,7 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
|
|||
* 2 not slave transmitter
|
||||
* 0 ok
|
||||
*/
|
||||
uint8_t twi_transmit(const uint8_t* data, uint8_t length)
|
||||
uint8_t twi_transmit(uint8_t* data, uint8_t length)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
|
@ -380,16 +349,7 @@ SIGNAL(TWI_vect)
|
|||
TWDR = twi_masterBuffer[twi_masterBufferIndex++];
|
||||
twi_reply(1);
|
||||
}else{
|
||||
if (twi_sendStop)
|
||||
twi_stop();
|
||||
else {
|
||||
twi_inRepStart = true; // we're gonna send the START
|
||||
// don't enable the interrupt. We'll generate the start, but we
|
||||
// avoid handling the interrupt until we're in the next transaction,
|
||||
// at the point where we would normally issue the start.
|
||||
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
twi_stop();
|
||||
}
|
||||
break;
|
||||
case TW_MT_SLA_NACK: // address sent, nack received
|
||||
|
@ -420,17 +380,6 @@ SIGNAL(TWI_vect)
|
|||
case TW_MR_DATA_NACK: // data received, nack sent
|
||||
// put final byte into buffer
|
||||
twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
|
||||
if (twi_sendStop)
|
||||
twi_stop();
|
||||
else {
|
||||
twi_inRepStart = true; // we're gonna send the START
|
||||
// don't enable the interrupt. We'll generate the start, but we
|
||||
// avoid handling the interrupt until we're in the next transaction,
|
||||
// at the point where we would normally issue the start.
|
||||
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
break;
|
||||
case TW_MR_SLA_NACK: // address sent, nack received
|
||||
twi_stop();
|
||||
break;
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
//#define ATMEGA8
|
||||
|
||||
#ifndef CPU_FREQ
|
||||
#define CPU_FREQ 16000000L
|
||||
#endif
|
||||
|
||||
#ifndef TWI_FREQ
|
||||
#define TWI_FREQ 100000L
|
||||
#endif
|
||||
|
@ -40,9 +44,9 @@
|
|||
|
||||
void twi_init(void);
|
||||
void twi_setAddress(uint8_t);
|
||||
uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t);
|
||||
uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
|
||||
uint8_t twi_transmit(const uint8_t*, uint8_t);
|
||||
uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t);
|
||||
uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t);
|
||||
uint8_t twi_transmit(uint8_t*, uint8_t);
|
||||
void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
|
||||
void twi_attachSlaveTxEvent( void (*)(void) );
|
||||
void twi_reply(uint8_t);
|
|
@ -8,9 +8,12 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
SRC = firmware.c
|
||||
SRC = $(shell find -name '*.c')
|
||||
EXTRAINCDIRS = .
|
||||
|
||||
TEENSY_MAKE = $(MAKE) -f 'lib/teensy-makefile' SRC='$(SRC)'
|
||||
TEENSY_MAKE = $(MAKE) -f 'lib/pjrc/Makefile' \
|
||||
SRC='$(SRC)' \
|
||||
EXTRAINCDIRS='$(EXTRAINCDIRS)'
|
||||
|
||||
|
||||
.PHONY: all clean
|
||||
|
|
Loading…
Reference in New Issue