intermitent checkin; lots of stuff; i2c on hold; kb logic in progress
parent
b77e74cacd
commit
a288b8a045
|
@ -0,0 +1,3 @@
|
|||
*~
|
||||
*.swp
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
## Noob Electronics Stuff
|
||||
## Electronics Stuff
|
||||
|
||||
* [Resistor Color Codes]
|
||||
(http://www.ladyada.net/wiki/lib/exe/fetch.php?hash=a2c6a9&w=501&h=785&media=http%3A%2F%2Fwww.ladyada.net%2Fimages%2Fmetertutorial%2Frescolorcode.jpg)
|
||||
|
@ -34,8 +34,11 @@
|
|||
* [All About Circuits : Reference]
|
||||
(http://www.allaboutcircuits.com/vol_5/index.html)
|
||||
|
||||
* [Effects of Varying I2C Pull-Up Resistors]
|
||||
(http://dsscircuits.com/articles/effects-of-varying-i2c-pull-up-resistors.html) : article by Wayne Truchsess
|
||||
|
||||
## Noob C Stuff
|
||||
|
||||
## C Stuff
|
||||
|
||||
* [C Library Reference]
|
||||
(http://www.cplusplus.com/reference/)
|
||||
|
@ -60,18 +63,11 @@
|
|||
(http://www.ibiblio.org/pub/languages/fortran/append-c.html)
|
||||
(on <http://www.ibiblio.org/>)
|
||||
|
||||
* [C preprocessor and concatenation]
|
||||
(http://stackoverflow.com/questions/1489932/c-preprocessor-and-concatenation)
|
||||
(on <http://stackoverflow.com/>)
|
||||
|
||||
## Noob Other Stuff
|
||||
|
||||
* [Markdown: Syntax]
|
||||
(http://daringfireball.net/projects/markdown/syntax)
|
||||
|
||||
* [Keyboard Scan Rates]
|
||||
(http://geekhack.org/showwiki.php?title=Keyboard+scan+rates)
|
||||
list (on <http://geekhack.org/>)
|
||||
|
||||
|
||||
## AVR C stuff
|
||||
### For the AVR
|
||||
|
||||
* [AVR Libc Library Reference]
|
||||
(http://www.nongnu.org/avr-libc/user-manual/modules.html)
|
||||
|
@ -83,14 +79,47 @@
|
|||
* [A Brief Tutorial on Programming the AVR without Arduino] by Chris Kuethe
|
||||
(https://www.mainframe.cx/~ckuethe/avr-c-tutorial/)
|
||||
|
||||
## Protocol Stuff
|
||||
|
||||
## Articles / Tutorials
|
||||
### I²C
|
||||
|
||||
* [Arduino I²C Expansion IO]
|
||||
(http://www.neufeld.newton.ks.us/electronics/?p=241)
|
||||
(from [Keith's Electronics Blog]
|
||||
(http://www.neufeld.newton.ks.us/electronics/))
|
||||
|
||||
* [Arduino Playground :: Wire Library, Explored]
|
||||
(http://arduino.cc/playground/Main/WireLibraryDetailedReference)
|
||||
|
||||
### USB
|
||||
|
||||
* About Keyboard [Scan Codes]
|
||||
(http://geekhack.org/showwiki.php?title=Scan+Codes)
|
||||
(on <http://geekhack.org/>)
|
||||
|
||||
* [USB 2.0 Specification]
|
||||
(http://www.usb.org/developers/docs/usb_20_101111.zip)
|
||||
: zip (from <http://www.usb.org/developers/docs/>)
|
||||
|
||||
* [HID Device Class Definition]
|
||||
(http://www.usb.org/developers/devclass_docs/HID1_11.pdf)
|
||||
: pdf (from <http://www.usb.org/developers/hidpage>)
|
||||
* HID = Human Interface Device
|
||||
|
||||
* [HID Usage Tables]
|
||||
(http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf)
|
||||
: pdf (from <http://www.usb.org/developers/hidpage>)
|
||||
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
* [Markdown: Syntax]
|
||||
(http://daringfireball.net/projects/markdown/syntax)
|
||||
|
||||
* [Keyboard Scan Rates]
|
||||
(http://geekhack.org/showwiki.php?title=Keyboard+scan+rates)
|
||||
list (on <http://geekhack.org/>)
|
||||
|
||||
|
||||
## Other Firmware / Code
|
||||
|
||||
|
@ -192,7 +221,7 @@
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Released under The MIT License (MIT) (see "license.md") at
|
||||
<https://github.com/benblazak/ergodox-firmware>
|
||||
Copyright © 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (MIT) (see "license.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
|
|
13
readme.md
13
readme.md
|
@ -3,9 +3,16 @@
|
|||
[ergodox-firmware]: https://github.com/benblazak/ergodox-firmware
|
||||
[ergodox keyboard]: http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard
|
||||
|
||||
|
||||
## dependencies
|
||||
|
||||
* See the PJRC [Getting Started] (http://pjrc.com/teensy/first_use.html) page
|
||||
for instructions on how to set up an AVR programming environment. This
|
||||
project uses C (not Arduino).
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Released under The MIT License (MIT) (see "license.md") at
|
||||
<https://github.com/benblazak/ergodox-firmware>
|
||||
Copyright © 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (MIT) (see "license.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Firmware main file
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "lib/pjrc/print.h"
|
||||
// #include "lib/pjrc/print.h"
|
||||
|
||||
#include "keyboard.h"
|
||||
// #include "keyboard.h"
|
||||
|
||||
|
||||
// TODO
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout specific stuff
|
||||
* - public things are prefixed by `layout_` or `LAYOUT_`
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~ documentation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Matrix [row.column] assignments
|
||||
* - row and column numbers are in hex
|
||||
* - coordinates without brackets are unused
|
||||
* - left and right hands are mirrored, with `row += 6` for left hand rows
|
||||
* ----------------------------------------------------------------------------
|
||||
* ....... rows x columns = positions; assigned, unassigned .......
|
||||
* ....... per hand: 6 x 7 = 42; 38, 4 .......
|
||||
* ....... total: 12 x 7 = 84; 76, 8 .......
|
||||
* ----------------------------------------------------------------------------
|
||||
* [66][65][64][63][62][61][60] [00][01][02][03][04][05][06]
|
||||
* [76][75][74][73][72][71][70] [10][11][12][13][14][15][16]
|
||||
* [86][85][84][83][82][81] 80 20 [21][22][23][24][25][26]
|
||||
* [96][95][94][93][92][91][90] [30][31][32][33][34][35][36]
|
||||
* [A6][A5][A4][A3][A2] A1 A0 40 41 [42][43][44][45][46]
|
||||
* [B1] B0 50 [51]
|
||||
* [B3] [B2] [52] [53]
|
||||
* [B6][B5][B4] [54][55][56]
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "layout.h"
|
||||
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~ variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
// 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
|
||||
// --- 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
|
||||
// };
|
||||
//
|
||||
// TODO: this belongs in program space
|
||||
// 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
|
||||
// --- 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
|
||||
// };
|
||||
|
|
@ -1,16 +1,42 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* see "default.c"
|
||||
* ergoDOX layout
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak
|
||||
* Released under The MIT License (MIT) (see "license.md") at
|
||||
* <https://github.com/benblazak/ergodox-firmware>
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LAYOUT_h
|
||||
#define LAYOUT_h
|
||||
|
||||
#define LAYOUT_LAYERS 1
|
||||
#define LAYOUT_ROWS 12 // must match real life
|
||||
#define LAYOUT_COLUMNS 7 // must match real life
|
||||
#include "lib/usb/keyboard-usage-page.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#define KB_LAYERS 1 // anything >= 1, as long as there's memory
|
||||
|
||||
extern const uint8_t kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
// TODO (before release): put more effort into this
|
||||
// ------- layer 0: default -------
|
||||
// --- right hand ---
|
||||
/* 0 ---------- 1 --------------- 2 -------------- 3 ----------------- 4 --------------------- 5 -------------------------- 6 -------------------------- */
|
||||
/* 0 */ 0, KEY_6_Caret, KEY_7_Ampersand, KEY_8_Asterisk, KEY_9_LeftParenthesis, KEY_0_RightParenthesis, KEY_Dash_Underscore, /* 0 */
|
||||
/* 1 */ 0, KEY_y_Y, KEY_u_U, KEY_i_I, KEY_o_O, KEY_p_P, KEY_LeftBracket_LeftBrace, /* 1 */
|
||||
/* 2 */ 0,/*unused*/ KEY_h_H, KEY_j_J, KEY_k_K, KEY_l_L, KEY_Semicolon_Colon, KEY_SingleQuote_DoubleQuote, /* 2 */
|
||||
/* 3 */ 0, KEY_n_N, KEY_m_M, KEY_Comma_LessThan, KEY_Period_GreaterThan, KEY_Slash_Question, KEY_RightShift, /* 3 */
|
||||
/* 4 */ 0,/*unused*/ 0,/*unused*/ KEY_UpArrow, KEY_DownArrow, KEY_Backslash_Pipe, KEY_RightBracket_RightBrace, 0, /* 4 */
|
||||
/* 5 */ 0,/*unused*/ KEY_RightControl, KEY_RightAlt, KEY_PageUp, KEY_PageDown, KEY_ReturnEnter, KEY_Spacebar, /* 5 */
|
||||
/* 0 ---------- 1 --------------- 2 -------------- 3 ----------------- 4 --------------------- 5 -------------------------- 6 -------------------------- */
|
||||
// --- left hand ---
|
||||
/* 0 ------------------ 1 -------------------- 2 ----------------- 3 ------------ 4 -------------- 5 ------------ 6 ----------- */
|
||||
/* 6 */ KEY_Equal_Plus, KEY_1_Exclamation, KEY_2_At, KEY_3_Pound, KEY_4_Dollar, KEY_5_Percent, 0, /* 6 */
|
||||
/* 7 */ KEY_Tab, KEY_q_Q, KEY_w_W, KEY_e_E, KEY_r_R, KEY_t_T, 0, /* 7 */
|
||||
/* 8 */ KEY_CapsLock, KEY_a_A, KEY_s_S, KEY_d_D, KEY_f_F, KEY_g_G, 0,/*unused*/ /* 8 */
|
||||
/* 9 */ KEY_LeftShift, KEY_z_Z, KEY_x_X, KEY_c_C, KEY_v_V, KEY_b_B, 0, /* 9 */
|
||||
/* A */ 0, KEY_GraveAccent_Tilde, KEY_Backslash_Pipe, KEY_LeftArrow, KEY_RightArrow, 0,/*unused*/ 0,/*unused*/ /* A */
|
||||
/* B */ KEY_DeleteBackspace, KEY_DeleteForward, KEY_End, KEY_Home, KEY_LeftAlt, KEY_LeftControl, 0, 0 /*unused*/ /* B */
|
||||
/* 0 ------------------ 1 -------------------- 2 ----------------- 3 ------------ 4 -------------- 5 ------------ 6 ----------- */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// TODO
|
||||
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
#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,22 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX: keyboard matrix specific exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef MATRIX_h
|
||||
#define MATRIX_h
|
||||
|
||||
#include "lib/data-types.h"
|
||||
|
||||
#define KB_ROWS 12 // must match real life
|
||||
#define KB_COLUMNS 7 // must match real life
|
||||
|
||||
extern bool kb_is_pressed[KB_ROWS][KB_COLUMNS];
|
||||
bool kb_is_pressed[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# Documentation : Keyboard Matrix
|
||||
|
||||
## Matrix [row.column] assignments
|
||||
|
||||
* row and column numbers are in hex
|
||||
* coordinates without brackets are unused
|
||||
* left and right hands are mostly the same, except that `row += 6` for left
|
||||
hand rows
|
||||
|
||||
....... rows x columns = positions; assigned, unassigned .......
|
||||
....... per hand: 6 x 7 = 42; 38, 4 .......
|
||||
....... total: 12 x 7 = 84; 76, 8 .......
|
||||
----------------------------------------------------------------------------
|
||||
[60][61][62][63][64][65][66] [00][01][02][03][04][05][06]
|
||||
[70][71][72][73][74][75][76] [10][11][12][13][14][15][16]
|
||||
[80][81][82][83][84][85] 86 20 [21][22][23][24][25][26]
|
||||
[90][91][92][93][94][95][96] [30][31][32][33][34][35][36]
|
||||
[A0][A1][A2][A3][A4] A5 A6 40 41 [42][43][44][45][46]
|
||||
[B0] B6 50 [56]
|
||||
[B1] [B5] [51] [55]
|
||||
[B2][B3][B4] [52][53][54]
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (MIT) (see "license.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
|
@ -1,16 +1,80 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
// TODO: this is not working yet
|
||||
|
||||
#define TWI_ADDRESS MCP23018_TWI_ADDRESS // from header file
|
||||
#if 0 // this is not the one we want; but it has all the right info
|
||||
#include "lib-other/peter-fleury/i2cmaster/i2cmaster.h"
|
||||
|
||||
// so we can say `TWI_ADDRESS|I2C_WRITE`
|
||||
#define TWI_ADDRESS (MCP23018_TWI_ADDRESS<<1)
|
||||
|
||||
uint8_t mcp23018_ready; // false
|
||||
|
||||
uint8_t mcp23018_init(void) {
|
||||
// declare vars
|
||||
uint8_t error;
|
||||
|
||||
// see if the device is ready
|
||||
// - success: set `mcp23018_ready = true` and continue initializing
|
||||
// - failure: return `error`; we can try again later
|
||||
error = i2c_start(TWI_ADDRESS|I2C_WRITE);
|
||||
if(error) {
|
||||
return error;
|
||||
} else {
|
||||
mcp23018_ready = true;
|
||||
i2c_stop(); // release bus
|
||||
}
|
||||
|
||||
// set pin direction
|
||||
// - unused : input : 1
|
||||
// - rows : output : 0
|
||||
// - columns : input : 1
|
||||
i2c_start_wait(TWI_ADDRESS|I2C_WRITE);
|
||||
i2c_write(IODIRA); // start register address
|
||||
i2c_write(0b11000000); // IODIRA
|
||||
i2c_write(0b11111111); // IODIRB
|
||||
i2c_stop();
|
||||
|
||||
// set pull-up
|
||||
// - unused : on : 1
|
||||
// - rows : on : 1
|
||||
// - columns : on : 1
|
||||
i2c_start_wait(TWI_ADDRESS|I2C_WRITE);
|
||||
i2c_write(GPPUA); // start register address
|
||||
i2c_write(0b11111111); // GPPUA
|
||||
i2c_write(0b11111111); // GPPUB
|
||||
i2c_stop();
|
||||
|
||||
// set output pins high
|
||||
// - rows : high : 1
|
||||
// - other : low : 0 (or ignored)
|
||||
i2c_start_wait(TWI_ADDRESS|I2C_WRITE);
|
||||
i2c_write(OLATA); // start register address
|
||||
i2c_write(0b00111111); // OLATA
|
||||
i2c_stop();
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#include <util/delay.h>
|
||||
#include <util/twi.h>
|
||||
// #include "lib-other/arduino/arduino/libraries/Wire/utility/twi.h"
|
||||
#include "lib-other/pjrc/blinky/print.h"
|
||||
#include "lib-other/pjrc/blinky/usb_debug_only.h"
|
||||
|
||||
#define MCP23018_h_INCLUDE_PRIVATE
|
||||
#include "mcp23018.h"
|
||||
#include "teensy-2-0.h"
|
||||
#include "lib/data-types.h"
|
||||
|
||||
#define True ((uint8_t)1)
|
||||
#define False ((uint8_t)0)
|
||||
|
||||
// register addresses (see "mcp23018.md")
|
||||
#define IODIRA 0x00 // i/o direction register
|
||||
|
@ -22,40 +86,89 @@
|
|||
#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);
|
||||
static void twi_init(void) {
|
||||
// TWSR &= ~( (1<<TWPS1)|(1<<TWPS0) );
|
||||
TWSR |= (1<<TWPS1)|(1<<TWPS0); //dbg
|
||||
// TWBR = ((F_CPU / 100000) - 16) / 2;
|
||||
TWBR = 0xFF; //dbg
|
||||
// TWCR = (1<<TWEA)|(1<<TWEN);
|
||||
}
|
||||
|
||||
static uint8_t twi_start(void) {
|
||||
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
|
||||
while (!(TWCR & (1<<TWINT)));
|
||||
if ((TWSR & 0xF8) != TW_START)
|
||||
return TWSR & 0xF8; // error
|
||||
}
|
||||
|
||||
static void twi_stop(void) {
|
||||
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
|
||||
while (!(TWCR & (1<<TWSTO)));
|
||||
}
|
||||
|
||||
static uint8_t twi_send(uint8_t data) {
|
||||
TWDR = data;
|
||||
TWCR = (1<<TWINT)|(1<<TWEN);
|
||||
while (!(TWCR & (1<<TWINT)));
|
||||
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
|
||||
return TWSR & 0xF8; // error
|
||||
}
|
||||
|
||||
static void hid_print_number_binary(uint8_t data) {
|
||||
print("0b");
|
||||
for(int8_t i=7; i>=0; i--) {
|
||||
(data & (1<<i))
|
||||
? pchar('1')
|
||||
: pchar('0');
|
||||
}
|
||||
}
|
||||
static void hid_print_number_hex(uint8_t data) {
|
||||
print("0x"); phex(data);
|
||||
}
|
||||
static uint8_t try_address(uint8_t address) {
|
||||
uint8_t error;
|
||||
|
||||
print("\naddress "); hid_print_number_binary(address);
|
||||
twi_start();
|
||||
error = twi_send(address);
|
||||
twi_stop();
|
||||
print(" error "); hid_print_number_hex(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t mcp23018_init(void) {
|
||||
uint8_t error, address;
|
||||
|
||||
twi_init();
|
||||
|
||||
// send address, wait
|
||||
for (uint8_t i=0b000; i<=0b111; i++) {
|
||||
address = (0b0100<<4)|(i<<1)|TW_WRITE;
|
||||
error = try_address(address);
|
||||
}
|
||||
address = 0;
|
||||
error = try_address(address);
|
||||
// for (uint8_t i=0b0000000; i<=0b1111111; i++) {
|
||||
// address = (i<<1)|TW_WRITE;
|
||||
// error = try_address(address);
|
||||
// if (! error == 0x20)
|
||||
// return error;
|
||||
// }
|
||||
|
||||
|
||||
// uint8_t data[3];
|
||||
//
|
||||
// twi_init();
|
||||
// twi_setAddress(MCP23018_TWI_ADDRESS);
|
||||
//
|
||||
// data[0] = IODIRA;
|
||||
// data[1] = 0b00000000; // IODIRA
|
||||
// error = twi_writeTo(MCP23018_TWI_ADDRESS, data, 2, true);
|
||||
//
|
||||
// data[0] = OLATA; // start register address
|
||||
// data[1] = 0b00000000; // OLATA
|
||||
// twi_writeTo(MCP23018_TWI_ADDRESS, data, 2, true);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,26 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef MCP23018_h
|
||||
#define MCP23018_h
|
||||
#define MCP23018_h
|
||||
|
||||
#include "lib/data-types.h"
|
||||
|
||||
#define MCP23018_TWI_ADDRESS 0b0100000
|
||||
#ifdef MCP23018_h_INCLUDE_PRIVATE
|
||||
|
||||
#define MCP23018_TWI_ADDRESS 0b0100000
|
||||
|
||||
void mcp23018_init(void);
|
||||
extern bool mcp23018_ready;
|
||||
|
||||
uint8_t mcp23018_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
* 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.
|
||||
* Outputs are open drain, so we want pull-up resistors set for everything.
|
||||
|
||||
* abbreviations:
|
||||
* IODIR = I/O Direction Register
|
||||
|
@ -80,17 +81,17 @@
|
|||
|
||||
## 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 : 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
|
||||
|
|
||||
|
@ -121,7 +122,7 @@
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Released under The MIT License (MIT) (see "license.md") at
|
||||
<https://github.com/benblazak/ergodox-firmware>
|
||||
Copyright © 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (MIT) (see "license.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#define TEENSY_2_0_h_INCLUDE_PRIVATE
|
||||
#include "teensy-2-0.h"
|
||||
|
||||
|
||||
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define CPU_16MHz 0x00
|
||||
|
@ -19,47 +25,39 @@
|
|||
#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) {
|
||||
uint8_t 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
|
||||
DDRB &= ~0b00001110; // set B(3,2,1) as input
|
||||
PORTB |= 0b00001110; // set B(3,2,1) internal pull-up enabled
|
||||
DDRD &= ~0b01110000; // set D(6,5,4) as input
|
||||
PORTD |= 0b01110000; // set D(6,5,4) 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
|
||||
DDRB |= 0b11100000; // set B(7,6,5) 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
|
||||
DDRF |= 0b11110011; // set F(7,6,5,4,1,0) as output
|
||||
PORTF |= 0b11110011; // set F(7,6,5,4,1,0) 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
|
||||
DDRB &= ~0b00010001; // set B(4,0) as input
|
||||
PORTB |= 0b00010001; // set B(4,0) internal pull-up enabled
|
||||
DDRC &= ~0b11000000; // set C(7,6) as input
|
||||
PORTC |= 0b11000000; // set C(7,6) internal pull-up enabled
|
||||
DDRD &= ~0b10001100; // set D(7,3,2) as input
|
||||
PORTD |= 0b10001100; // set D(7,3,2) internal pull-up enabled
|
||||
|
||||
// I2C (TWI)
|
||||
twi_init(); // (on pins D(0,1))
|
||||
// on pins D(1,0); leave them alone here, so the TWI library can do as
|
||||
// it wishes
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
|
|
|
@ -10,46 +10,28 @@
|
|||
#ifndef TEENSY_2_0_h
|
||||
#define TEENSY_2_0_h
|
||||
|
||||
#ifndef INCLUDE_PREFIX
|
||||
#define INCLUDE_PREFIX teensy_
|
||||
#endif
|
||||
|
||||
#define prefix(s) INCLUDE_PREFIX##s
|
||||
#define pprefix(s) PRIVATE_INCLUDE_PREFIX##s
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <avr/io.h> // for the register macros
|
||||
|
||||
// LED control
|
||||
#define prefix(LED1_ON) (OCR1A = 0xFF)
|
||||
#define prefix(LED1_OFF) (OCR1A = 0x00)
|
||||
#define prefix(LED1_SET)(n) (OCR1A = (uint8_t)(n))
|
||||
#define prefix(LED1_SET_PERCENT)(n) (OCR1A = (uint8_t)((n) * 0xFF))
|
||||
#define prefix(LED2_ON) (OCR1B = 0xFF)
|
||||
#define prefix(LED2_OFF) (OCR1B = 0x00)
|
||||
#define prefix(LED2_SET)(n) (OCR1B = (uint8_t)(n))
|
||||
#define prefix(LED2_SET_PERCENT)(n) (OCR1B = (uint8_t)((n) * 0xFF))
|
||||
#define prefix(LED3_ON) (OCR1C = 0xFF)
|
||||
#define prefix(LED3_OFF) (OCR1C = 0x00)
|
||||
#define prefix(LED3_SET)(n) (OCR1C = (uint8_t)(n))
|
||||
#define prefix(LED3_SET_PERCENT)(n) (OCR1C = (uint8_t)((n) * 0xFF))
|
||||
#define KB_LED1_ON (OCR1A = 0xFF)
|
||||
#define KB_LED1_OFF (OCR1A = 0x00)
|
||||
#define KB_LED1_SET(n) (OCR1A = (uint8_t)(n))
|
||||
#define KB_LED1_SET_PERCENT(n) (OCR1A = (uint8_t)((n) * 0xFF))
|
||||
#define KB_LED2_ON (OCR1B = 0xFF)
|
||||
#define KB_LED2_OFF (OCR1B = 0x00)
|
||||
#define KB_LED2_SET(n) (OCR1B = (uint8_t)(n))
|
||||
#define KB_LED2_SET_PERCENT(n) (OCR1B = (uint8_t)((n) * 0xFF))
|
||||
#define KB_LED3_ON (OCR1C = 0xFF)
|
||||
#define KB_LED3_OFF (OCR1C = 0x00)
|
||||
#define KB_LED3_SET(n) (OCR1C = (uint8_t)(n))
|
||||
#define KB_LED3_SET_PERCENT(n) (OCR1C = (uint8_t)((n) * 0xFF))
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifdef PRIVATE_INCLUDE_PREFIX
|
||||
#ifdef TEENSY_2_0_h_INCLUDE_PRIVATE
|
||||
|
||||
void pprefix(init)(void)
|
||||
__attribute__((alias ("teensy_init")));
|
||||
uint8_t teensy_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#undef prefix
|
||||
#undef pprefix
|
||||
#undef INCLUDE_PREFIX
|
||||
#undef PRIVATE_INCLUDE_PREFIX
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -41,10 +41,10 @@
|
|||
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.
|
||||
* SCL and SDA: Need external pull-up resistors. Sometimes the Teensy
|
||||
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
|
||||
|
||||
|
@ -94,7 +94,7 @@
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Released under The MIT License (MIT) (see "license.md") at
|
||||
<https://github.com/benblazak/ergodox-firmware>
|
||||
Copyright © 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (MIT) (see "license.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
|
|
|
@ -0,0 +1,473 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
|
||||
<title>AVR-GCC libraries: I2C Master library</title>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
</head><body>
|
||||
<!-- Generated by Doxygen 1.4.1 -->
|
||||
<h1>I2C Master library</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
|
||||
I2C (TWI) Master Software Library.
|
||||
<p>
|
||||
<div class="fragment"><pre class="fragment"><span class="preprocessor"> #include <i2cmaster.h></span>
|
||||
</pre></div><p>
|
||||
Basic routines for communicating with I2C slave devices. This single master implementation is limited to one bus master on the I2C bus.<p>
|
||||
This I2c library is implemented as a compact assembler software implementation of the I2C protocol which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c). Since the API for these two implementations is exactly the same, an application can be linked either against the software I2C implementation or the hardware I2C implementation.<p>
|
||||
Use 4.7k pull-up resistor on the SDA and SCL pin.<p>
|
||||
Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module i2cmaster.S to your target when using the software I2C implementation !<p>
|
||||
Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.<p>
|
||||
<dl compact><dt><b>Note:</b></dt><dd>The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted to GNU assembler and AVR-GCC C call interface. Replaced the incorrect quarter period delays found in AVR300 with half period delays.</dd></dl>
|
||||
<dl compact><dt><b>Author:</b></dt><dd>Peter Fleury <a href="mailto:pfleury@gmx.ch">pfleury@gmx.ch</a> <a href="http://jump.to/fleury">http://jump.to/fleury</a></dd></dl>
|
||||
<dl compact><dt><b>API Usage Example</b></dt><dd>The following code shows typical usage of this library, see example test_i2cmaster.c</dd></dl>
|
||||
<div class="fragment"><pre class="fragment"><span class="preprocessor"> #include <i2cmaster.h></span>
|
||||
|
||||
|
||||
<span class="preprocessor"> #define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet</span>
|
||||
<span class="preprocessor"></span>
|
||||
<span class="keywordtype">int</span> main(<span class="keywordtype">void</span>)
|
||||
{
|
||||
<span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> ret;
|
||||
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga0">i2c_init</a>(); <span class="comment">// initialize I2C library</span>
|
||||
|
||||
<span class="comment">// write 0x75 to EEPROM address 5 (Byte Write) </span>
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga4">i2c_start_wait</a>(Dev24C02+I2C_WRITE); <span class="comment">// set device address and write mode</span>
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga5">i2c_write</a>(0x05); <span class="comment">// write address = 5</span>
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga5">i2c_write</a>(0x75); <span class="comment">// write value 0x75 to EEPROM</span>
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga1">i2c_stop</a>(); <span class="comment">// set stop conditon = release bus</span>
|
||||
|
||||
|
||||
<span class="comment">// read previously written value back from EEPROM address 5 </span>
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga4">i2c_start_wait</a>(Dev24C02+I2C_WRITE); <span class="comment">// set device address and write mode</span>
|
||||
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga5">i2c_write</a>(0x05); <span class="comment">// write address = 5</span>
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga3">i2c_rep_start</a>(Dev24C02+I2C_READ); <span class="comment">// set device address and read mode</span>
|
||||
|
||||
ret = <a class="code" href="group__pfleury__ic2master.html#ga7">i2c_readNak</a>(); <span class="comment">// read one byte from EEPROM</span>
|
||||
<a class="code" href="group__pfleury__ic2master.html#ga1">i2c_stop</a>();
|
||||
|
||||
<span class="keywordflow">for</span>(;;);
|
||||
}
|
||||
</pre></div>
|
||||
<p>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan="2"><br><h2>Defines</h2></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga9">I2C_READ</a> 1</td></tr>
|
||||
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga10">I2C_WRITE</a> 0</td></tr>
|
||||
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga11" doxytag="pfleury_ic2master::i2c_read"></a>
|
||||
#define </td><td class="memItemRight" valign="bottom"><b>i2c_read</b>(ack) (ack) ? i2c_readAck() : i2c_readNak();</td></tr>
|
||||
|
||||
<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga0">i2c_init</a> (void)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">initialize the I2C master interace. Need to be called only once <a href="#ga0"></a><br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga1">i2c_stop</a> (void)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Terminates the data transfer and releases the I2C bus. <a href="#ga1"></a><br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned char </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga2">i2c_start</a> (unsigned char addr)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Issues a start condition and sends address and transfer direction. <a href="#ga2"></a><br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned char </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga3">i2c_rep_start</a> (unsigned char addr)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Issues a repeated start condition and sends address and transfer direction. <a href="#ga3"></a><br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga4">i2c_start_wait</a> (unsigned char addr)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Issues a start condition and sends address and transfer direction. <a href="#ga4"></a><br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned char </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga5">i2c_write</a> (unsigned char data)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Send one byte to I2C device. <a href="#ga5"></a><br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned char </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga6">i2c_readAck</a> (void)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">read one byte from the I2C device, request more data from device <a href="#ga6"></a><br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned char </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga7">i2c_readNak</a> (void)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">read one byte from the I2C device, read is followed by a stop condition <a href="#ga7"></a><br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned char </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__ic2master.html#ga8">i2c_read</a> (unsigned char ack)</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">read one byte from the I2C device <a href="#ga8"></a><br></td></tr>
|
||||
</table>
|
||||
<hr><h2>Define Documentation</h2>
|
||||
<a class="anchor" name="ga9" doxytag="i2cmaster.h::I2C_READ"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">#define I2C_READ 1 </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
defines the data direction (reading from I2C device) in <a class="el" href="group__pfleury__ic2master.html#ga2">i2c_start()</a>,<a class="el" href="group__pfleury__ic2master.html#ga3">i2c_rep_start()</a> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga10" doxytag="i2cmaster.h::I2C_WRITE"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">#define I2C_WRITE 0 </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
defines the data direction (writing to I2C device) in <a class="el" href="group__pfleury__ic2master.html#ga2">i2c_start()</a>,<a class="el" href="group__pfleury__ic2master.html#ga3">i2c_rep_start()</a> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr><h2>Function Documentation</h2>
|
||||
<a class="anchor" name="ga0" doxytag="i2cmaster.h::i2c_init"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">void i2c_init </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">void </td>
|
||||
<td class="mdname1" valign="top" nowrap> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
initialize the I2C master interace. Need to be called only once
|
||||
<p>
|
||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>void</em> </td><td></td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
<dl compact><dt><b>Returns:</b></dt><dd>none </dd></dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga1" doxytag="i2cmaster.h::i2c_stop"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">void i2c_stop </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">void </td>
|
||||
<td class="mdname1" valign="top" nowrap> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Terminates the data transfer and releases the I2C bus.
|
||||
<p>
|
||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>void</em> </td><td></td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
<dl compact><dt><b>Returns:</b></dt><dd>none </dd></dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga2" doxytag="i2cmaster.h::i2c_start"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">unsigned char i2c_start </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">unsigned char </td>
|
||||
<td class="mdname1" valign="top" nowrap> <em>addr</em> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Issues a start condition and sends address and transfer direction.
|
||||
<p>
|
||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>addr</em> </td><td>address and transfer direction of I2C device </td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
<dl compact><dt><b>Return values:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>0</em> </td><td>device accessible </td></tr>
|
||||
<tr><td valign="top"></td><td valign="top"><em>1</em> </td><td>failed to access device </td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga3" doxytag="i2cmaster.h::i2c_rep_start"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">unsigned char i2c_rep_start </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">unsigned char </td>
|
||||
<td class="mdname1" valign="top" nowrap> <em>addr</em> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Issues a repeated start condition and sends address and transfer direction.
|
||||
<p>
|
||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>addr</em> </td><td>address and transfer direction of I2C device </td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
<dl compact><dt><b>Return values:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>0</em> </td><td>device accessible </td></tr>
|
||||
<tr><td valign="top"></td><td valign="top"><em>1</em> </td><td>failed to access device </td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga4" doxytag="i2cmaster.h::i2c_start_wait"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">void i2c_start_wait </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">unsigned char </td>
|
||||
<td class="mdname1" valign="top" nowrap> <em>addr</em> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Issues a start condition and sends address and transfer direction.
|
||||
<p>
|
||||
If device is busy, use ack polling to wait until device ready <dl compact><dt><b>Parameters:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>addr</em> </td><td>address and transfer direction of I2C device </td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
<dl compact><dt><b>Returns:</b></dt><dd>none </dd></dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga5" doxytag="i2cmaster.h::i2c_write"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">unsigned char i2c_write </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">unsigned char </td>
|
||||
<td class="mdname1" valign="top" nowrap> <em>data</em> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Send one byte to I2C device.
|
||||
<p>
|
||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>data</em> </td><td>byte to be transfered </td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
<dl compact><dt><b>Return values:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>0</em> </td><td>write successful </td></tr>
|
||||
<tr><td valign="top"></td><td valign="top"><em>1</em> </td><td>write failed </td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga6" doxytag="i2cmaster.h::i2c_readAck"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">unsigned char i2c_readAck </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">void </td>
|
||||
<td class="mdname1" valign="top" nowrap> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
read one byte from the I2C device, request more data from device
|
||||
<p>
|
||||
<dl compact><dt><b>Returns:</b></dt><dd>byte read from I2C device </dd></dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga7" doxytag="i2cmaster.h::i2c_readNak"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">unsigned char i2c_readNak </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">void </td>
|
||||
<td class="mdname1" valign="top" nowrap> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
read one byte from the I2C device, read is followed by a stop condition
|
||||
<p>
|
||||
<dl compact><dt><b>Returns:</b></dt><dd>byte read from I2C device </dd></dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="anchor" name="ga8" doxytag="i2cmaster.h::i2c_read"></a><p>
|
||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td class="mdRow">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md" nowrap valign="top">unsigned char i2c_read </td>
|
||||
<td class="md" valign="top">( </td>
|
||||
<td class="md" nowrap valign="top">unsigned char </td>
|
||||
<td class="mdname1" valign="top" nowrap> <em>ack</em> </td>
|
||||
<td class="md" valign="top"> ) </td>
|
||||
<td class="md" nowrap></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
read one byte from the I2C device
|
||||
<p>
|
||||
Implemented as a macro, which calls either i2c_readAck or i2c_readNak<p>
|
||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr><td valign="top"></td><td valign="top"><em>ack</em> </td><td>1 send ack, request more data from device<br>
|
||||
0 send nak, read is followed by a stop condition </td></tr>
|
||||
</table>
|
||||
</dl>
|
||||
<dl compact><dt><b>Returns:</b></dt><dd>byte read from I2C device </dd></dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr size="1"><address style="align: right;"><small>Generated on Tue Mar 29 16:54:08 2005 for AVR-GCC libraries by
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.1 </small></address>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,302 @@
|
|||
;*************************************************************************
|
||||
; Title : I2C (Single) Master Implementation
|
||||
; Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||||
; based on Atmel Appl. Note AVR300
|
||||
; File: $Id: i2cmaster.S,v 1.12 2008/03/02 08:51:27 peter Exp $
|
||||
; Software: AVR-GCC 3.3 or higher
|
||||
; Target: any AVR device
|
||||
;
|
||||
; DESCRIPTION
|
||||
; Basic routines for communicating with I2C slave devices. This
|
||||
; "single" master implementation is limited to one bus master on the
|
||||
; I2C bus.
|
||||
;
|
||||
; Based on the Atmel Application Note AVR300, corrected and adapted
|
||||
; to GNU assembler and AVR-GCC C call interface
|
||||
; Replaced the incorrect quarter period delays found in AVR300 with
|
||||
; half period delays.
|
||||
;
|
||||
; USAGE
|
||||
; These routines can be called from C, refere to file i2cmaster.h.
|
||||
; See example test_i2cmaster.c
|
||||
; Adapt the SCL and SDA port and pin definitions and eventually
|
||||
; the delay routine to your target !
|
||||
; Use 4.7k pull-up resistor on the SDA and SCL pin.
|
||||
;
|
||||
; NOTES
|
||||
; The I2C routines can be called either from non-interrupt or
|
||||
; interrupt routines, not both.
|
||||
;
|
||||
;*************************************************************************
|
||||
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 303
|
||||
#error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !"
|
||||
#endif
|
||||
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
|
||||
|
||||
;***** Adapt these SCA and SCL port and pin definition to your target !!
|
||||
;
|
||||
#define SDA 4 // SDA Port D, Pin 4
|
||||
#define SCL 5 // SCL Port D, Pin 5
|
||||
#define SDA_PORT PORTD // SDA Port D
|
||||
#define SCL_PORT PORTD // SCL Port D
|
||||
|
||||
;******
|
||||
|
||||
;-- map the IO register back into the IO address space
|
||||
#define SDA_DDR (_SFR_IO_ADDR(SDA_PORT) - 1)
|
||||
#define SCL_DDR (_SFR_IO_ADDR(SCL_PORT) - 1)
|
||||
#define SDA_OUT _SFR_IO_ADDR(SDA_PORT)
|
||||
#define SCL_OUT _SFR_IO_ADDR(SCL_PORT)
|
||||
#define SDA_IN (_SFR_IO_ADDR(SDA_PORT) - 2)
|
||||
#define SCL_IN (_SFR_IO_ADDR(SCL_PORT) - 2)
|
||||
|
||||
|
||||
#ifndef __tmp_reg__
|
||||
#define __tmp_reg__ 0
|
||||
#endif
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
;*************************************************************************
|
||||
; delay half period
|
||||
; For I2C in normal mode (100kHz), use T/2 > 5us
|
||||
; For I2C in fast mode (400kHz), use T/2 > 1.3us
|
||||
;*************************************************************************
|
||||
.stabs "",100,0,0,i2c_delay_T2
|
||||
.stabs "i2cmaster.S",100,0,0,i2c_delay_T2
|
||||
.func i2c_delay_T2 ; delay 5.0 microsec with 4 Mhz crystal
|
||||
i2c_delay_T2: ; 4 cycles
|
||||
rjmp 1f ; 2 "
|
||||
1: rjmp 2f ; 2 "
|
||||
2: rjmp 3f ; 2 "
|
||||
3: rjmp 4f ; 2 "
|
||||
4: rjmp 5f ; 2 "
|
||||
5: rjmp 6f ; 2 "
|
||||
6: nop ; 1 "
|
||||
ret ; 3 "
|
||||
.endfunc ; total 20 cyles = 5.0 microsec with 4 Mhz crystal
|
||||
|
||||
|
||||
;*************************************************************************
|
||||
; Initialization of the I2C bus interface. Need to be called only once
|
||||
;
|
||||
; extern void i2c_init(void)
|
||||
;*************************************************************************
|
||||
.global i2c_init
|
||||
.func i2c_init
|
||||
i2c_init:
|
||||
cbi SDA_DDR,SDA ;release SDA
|
||||
cbi SCL_DDR,SCL ;release SCL
|
||||
cbi SDA_OUT,SDA
|
||||
cbi SCL_OUT,SCL
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
;*************************************************************************
|
||||
; Issues a start condition and sends address and transfer direction.
|
||||
; return 0 = device accessible, 1= failed to access device
|
||||
;
|
||||
; extern unsigned char i2c_start(unsigned char addr);
|
||||
; addr = r24, return = r25(=0):r24
|
||||
;*************************************************************************
|
||||
|
||||
.global i2c_start
|
||||
.func i2c_start
|
||||
i2c_start:
|
||||
sbi SDA_DDR,SDA ;force SDA low
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
|
||||
rcall i2c_write ;write address
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
;*************************************************************************
|
||||
; Issues a repeated start condition and sends address and transfer direction.
|
||||
; return 0 = device accessible, 1= failed to access device
|
||||
;
|
||||
; extern unsigned char i2c_rep_start(unsigned char addr);
|
||||
; addr = r24, return = r25(=0):r24
|
||||
;*************************************************************************
|
||||
|
||||
.global i2c_rep_start
|
||||
.func i2c_rep_start
|
||||
i2c_rep_start:
|
||||
sbi SCL_DDR,SCL ;force SCL low
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
cbi SDA_DDR,SDA ;release SDA
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
cbi SCL_DDR,SCL ;release SCL
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
sbi SDA_DDR,SDA ;force SDA low
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
|
||||
rcall i2c_write ;write address
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
;*************************************************************************
|
||||
; Issues a start condition and sends address and transfer direction.
|
||||
; If device is busy, use ack polling to wait until device is ready
|
||||
;
|
||||
; extern void i2c_start_wait(unsigned char addr);
|
||||
; addr = r24
|
||||
;*************************************************************************
|
||||
|
||||
.global i2c_start_wait
|
||||
.func i2c_start_wait
|
||||
i2c_start_wait:
|
||||
mov __tmp_reg__,r24
|
||||
i2c_start_wait1:
|
||||
sbi SDA_DDR,SDA ;force SDA low
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
mov r24,__tmp_reg__
|
||||
rcall i2c_write ;write address
|
||||
tst r24 ;if device not busy -> done
|
||||
breq i2c_start_wait_done
|
||||
rcall i2c_stop ;terminate write operation
|
||||
rjmp i2c_start_wait1 ;device busy, poll ack again
|
||||
i2c_start_wait_done:
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
;*************************************************************************
|
||||
; Terminates the data transfer and releases the I2C bus
|
||||
;
|
||||
; extern void i2c_stop(void)
|
||||
;*************************************************************************
|
||||
|
||||
.global i2c_stop
|
||||
.func i2c_stop
|
||||
i2c_stop:
|
||||
sbi SCL_DDR,SCL ;force SCL low
|
||||
sbi SDA_DDR,SDA ;force SDA low
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
cbi SCL_DDR,SCL ;release SCL
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
cbi SDA_DDR,SDA ;release SDA
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
;*************************************************************************
|
||||
; Send one byte to I2C device
|
||||
; return 0 = write successful, 1 = write failed
|
||||
;
|
||||
; extern unsigned char i2c_write( unsigned char data );
|
||||
; data = r24, return = r25(=0):r24
|
||||
;*************************************************************************
|
||||
.global i2c_write
|
||||
.func i2c_write
|
||||
i2c_write:
|
||||
sec ;set carry flag
|
||||
rol r24 ;shift in carry and out bit one
|
||||
rjmp i2c_write_first
|
||||
i2c_write_bit:
|
||||
lsl r24 ;if transmit register empty
|
||||
i2c_write_first:
|
||||
breq i2c_get_ack
|
||||
sbi SCL_DDR,SCL ;force SCL low
|
||||
brcc i2c_write_low
|
||||
nop
|
||||
cbi SDA_DDR,SDA ;release SDA
|
||||
rjmp i2c_write_high
|
||||
i2c_write_low:
|
||||
sbi SDA_DDR,SDA ;force SDA low
|
||||
rjmp i2c_write_high
|
||||
i2c_write_high:
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
cbi SCL_DDR,SCL ;release SCL
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
rjmp i2c_write_bit
|
||||
|
||||
i2c_get_ack:
|
||||
sbi SCL_DDR,SCL ;force SCL low
|
||||
cbi SDA_DDR,SDA ;release SDA
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
cbi SCL_DDR,SCL ;release SCL
|
||||
i2c_ack_wait:
|
||||
sbis SCL_IN,SCL ;wait SCL high (in case wait states are inserted)
|
||||
rjmp i2c_ack_wait
|
||||
|
||||
clr r24 ;return 0
|
||||
sbic SDA_IN,SDA ;if SDA high -> return 1
|
||||
ldi r24,1
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
clr r25
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
|
||||
;*************************************************************************
|
||||
; read one byte from the I2C device, send ack or nak to device
|
||||
; (ack=1, send ack, request more data from device
|
||||
; ack=0, send nak, read is followed by a stop condition)
|
||||
;
|
||||
; extern unsigned char i2c_read(unsigned char ack);
|
||||
; ack = r24, return = r25(=0):r24
|
||||
; extern unsigned char i2c_readAck(void);
|
||||
; extern unsigned char i2c_readNak(void);
|
||||
; return = r25(=0):r24
|
||||
;*************************************************************************
|
||||
.global i2c_readAck
|
||||
.global i2c_readNak
|
||||
.global i2c_read
|
||||
.func i2c_read
|
||||
i2c_readNak:
|
||||
clr r24
|
||||
rjmp i2c_read
|
||||
i2c_readAck:
|
||||
ldi r24,0x01
|
||||
i2c_read:
|
||||
ldi r23,0x01 ;data = 0x01
|
||||
i2c_read_bit:
|
||||
sbi SCL_DDR,SCL ;force SCL low
|
||||
cbi SDA_DDR,SDA ;release SDA (from previous ACK)
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
|
||||
cbi SCL_DDR,SCL ;release SCL
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
|
||||
i2c_read_stretch:
|
||||
sbis SCL_IN, SCL ;loop until SCL is high (allow slave to stretch SCL)
|
||||
rjmp i2c_read_stretch
|
||||
|
||||
clc ;clear carry flag
|
||||
sbic SDA_IN,SDA ;if SDA is high
|
||||
sec ; set carry flag
|
||||
|
||||
rol r23 ;store bit
|
||||
brcc i2c_read_bit ;while receive register not full
|
||||
|
||||
i2c_put_ack:
|
||||
sbi SCL_DDR,SCL ;force SCL low
|
||||
cpi r24,1
|
||||
breq i2c_put_ack_low ;if (ack=0)
|
||||
cbi SDA_DDR,SDA ; release SDA
|
||||
rjmp i2c_put_ack_high
|
||||
i2c_put_ack_low: ;else
|
||||
sbi SDA_DDR,SDA ; force SDA low
|
||||
i2c_put_ack_high:
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
cbi SCL_DDR,SCL ;release SCL
|
||||
i2c_put_ack_wait:
|
||||
sbis SCL_IN,SCL ;wait SCL high
|
||||
rjmp i2c_put_ack_wait
|
||||
rcall i2c_delay_T2 ;delay T/2
|
||||
mov r24,r23
|
||||
clr r25
|
||||
ret
|
||||
.endfunc
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
#ifndef _I2CMASTER_H
|
||||
#define _I2CMASTER_H 1
|
||||
/*************************************************************************
|
||||
* Title: C include file for the I2C master interface
|
||||
* (i2cmaster.S or twimaster.c)
|
||||
* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||||
* File: $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
|
||||
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
|
||||
* Target: any AVR device
|
||||
* Usage: see Doxygen manual
|
||||
**************************************************************************/
|
||||
|
||||
#ifdef DOXYGEN
|
||||
/**
|
||||
@defgroup pfleury_ic2master I2C Master library
|
||||
@code #include <i2cmaster.h> @endcode
|
||||
|
||||
@brief I2C (TWI) Master Software Library
|
||||
|
||||
Basic routines for communicating with I2C slave devices. This single master
|
||||
implementation is limited to one bus master on the I2C bus.
|
||||
|
||||
This I2c library is implemented as a compact assembler software implementation of the I2C protocol
|
||||
which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
|
||||
Since the API for these two implementations is exactly the same, an application can be linked either against the
|
||||
software I2C implementation or the hardware I2C implementation.
|
||||
|
||||
Use 4.7k pull-up resistor on the SDA and SCL pin.
|
||||
|
||||
Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
|
||||
i2cmaster.S to your target when using the software I2C implementation !
|
||||
|
||||
Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.
|
||||
|
||||
@note
|
||||
The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
|
||||
to GNU assembler and AVR-GCC C call interface.
|
||||
Replaced the incorrect quarter period delays found in AVR300 with
|
||||
half period delays.
|
||||
|
||||
@author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
|
||||
|
||||
@par API Usage Example
|
||||
The following code shows typical usage of this library, see example test_i2cmaster.c
|
||||
|
||||
@code
|
||||
|
||||
#include <i2cmaster.h>
|
||||
|
||||
|
||||
#define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned char ret;
|
||||
|
||||
i2c_init(); // initialize I2C library
|
||||
|
||||
// write 0x75 to EEPROM address 5 (Byte Write)
|
||||
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
|
||||
i2c_write(0x05); // write address = 5
|
||||
i2c_write(0x75); // write value 0x75 to EEPROM
|
||||
i2c_stop(); // set stop conditon = release bus
|
||||
|
||||
|
||||
// read previously written value back from EEPROM address 5
|
||||
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
|
||||
|
||||
i2c_write(0x05); // write address = 5
|
||||
i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode
|
||||
|
||||
ret = i2c_readNak(); // read one byte from EEPROM
|
||||
i2c_stop();
|
||||
|
||||
for(;;);
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
#endif /* DOXYGEN */
|
||||
|
||||
/**@{*/
|
||||
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
|
||||
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
|
||||
#endif
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
|
||||
#define I2C_READ 1
|
||||
|
||||
/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
|
||||
#define I2C_WRITE 0
|
||||
|
||||
|
||||
/**
|
||||
@brief initialize the I2C master interace. Need to be called only once
|
||||
@param void
|
||||
@return none
|
||||
*/
|
||||
extern void i2c_init(void);
|
||||
|
||||
|
||||
/**
|
||||
@brief Terminates the data transfer and releases the I2C bus
|
||||
@param void
|
||||
@return none
|
||||
*/
|
||||
extern void i2c_stop(void);
|
||||
|
||||
|
||||
/**
|
||||
@brief Issues a start condition and sends address and transfer direction
|
||||
|
||||
@param addr address and transfer direction of I2C device
|
||||
@retval 0 device accessible
|
||||
@retval 1 failed to access device
|
||||
*/
|
||||
extern unsigned char i2c_start(unsigned char addr);
|
||||
|
||||
|
||||
/**
|
||||
@brief Issues a repeated start condition and sends address and transfer direction
|
||||
|
||||
@param addr address and transfer direction of I2C device
|
||||
@retval 0 device accessible
|
||||
@retval 1 failed to access device
|
||||
*/
|
||||
extern unsigned char i2c_rep_start(unsigned char addr);
|
||||
|
||||
|
||||
/**
|
||||
@brief Issues a start condition and sends address and transfer direction
|
||||
|
||||
If device is busy, use ack polling to wait until device ready
|
||||
@param addr address and transfer direction of I2C device
|
||||
@return none
|
||||
*/
|
||||
extern void i2c_start_wait(unsigned char addr);
|
||||
|
||||
|
||||
/**
|
||||
@brief Send one byte to I2C device
|
||||
@param data byte to be transfered
|
||||
@retval 0 write successful
|
||||
@retval 1 write failed
|
||||
*/
|
||||
extern unsigned char i2c_write(unsigned char data);
|
||||
|
||||
|
||||
/**
|
||||
@brief read one byte from the I2C device, request more data from device
|
||||
@return byte read from I2C device
|
||||
*/
|
||||
extern unsigned char i2c_readAck(void);
|
||||
|
||||
/**
|
||||
@brief read one byte from the I2C device, read is followed by a stop condition
|
||||
@return byte read from I2C device
|
||||
*/
|
||||
extern unsigned char i2c_readNak(void);
|
||||
|
||||
/**
|
||||
@brief read one byte from the I2C device
|
||||
|
||||
Implemented as a macro, which calls either i2c_readAck or i2c_readNak
|
||||
|
||||
@param ack 1 send ack, request more data from device<br>
|
||||
0 send nak, read is followed by a stop condition
|
||||
@return byte read from I2C device
|
||||
*/
|
||||
extern unsigned char i2c_read(unsigned char ack);
|
||||
#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
|
||||
|
||||
|
||||
/**@}*/
|
||||
#endif
|
|
@ -0,0 +1,392 @@
|
|||
# Makefile to compile and link the I2C Master library and test program
|
||||
#
|
||||
# based on
|
||||
# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
|
||||
#
|
||||
# Note:
|
||||
# The warnings which appear while converting ELF to AVR Extended COFF (make extcoff)
|
||||
# can be ignored
|
||||
#
|
||||
#
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
|
||||
# 4.07 or greater).
|
||||
#
|
||||
# make program = Download the hex file to the device, using avrdude. Please
|
||||
# customize the avrdude settings below first!
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#
|
||||
|
||||
|
||||
# MCU name
|
||||
MCU = at90s8515
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
OPT = s
|
||||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = test_i2cmaster
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c
|
||||
|
||||
# List Assembler source files here.
|
||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
||||
# will not be considered source files but generated files (assembler
|
||||
# output from the compiler), and will be deleted upon "make clean"!
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC = i2cmaster.S
|
||||
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
EXTRAINCDIRS =
|
||||
|
||||
|
||||
# Optional compiler flags.
|
||||
# -g: generate debugging information (for GDB, or for COFF conversion)
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see gcc manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlms: create assembler listing
|
||||
CFLAGS = -g -O$(OPT) \
|
||||
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
|
||||
-Wall -Wstrict-prototypes \
|
||||
-Wa,-adhlns=$(<:.c=.lst) \
|
||||
$(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
|
||||
|
||||
# Set a "language standard" compiler flag.
|
||||
# Unremark just one line below to set the language standard to use.
|
||||
# gnu99 = C99 + GNU extensions. See GCC manual for more information.
|
||||
#CFLAGS += -std=c89
|
||||
#CFLAGS += -std=gnu89
|
||||
#CFLAGS += -std=c99
|
||||
CFLAGS += -std=gnu99
|
||||
|
||||
|
||||
|
||||
# Optional assembler flags.
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlms: create listing
|
||||
# -gstabs: have the assembler create line number information; note that
|
||||
# for use in COFF files, additional information about filenames
|
||||
# and function names needs to be present in the assembler source
|
||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
||||
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
|
||||
|
||||
|
||||
|
||||
# Optional linker flags.
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
||||
|
||||
|
||||
|
||||
# Additional libraries
|
||||
|
||||
# Minimalistic printf version
|
||||
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
|
||||
|
||||
# Floating point printf version (requires -lm below)
|
||||
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
|
||||
|
||||
# -lm = math library
|
||||
LDFLAGS += -lm
|
||||
|
||||
|
||||
|
||||
|
||||
# Programming support using avrdude. Settings and variables.
|
||||
|
||||
# Programming hardware: alf avr910 avrisp bascom bsd
|
||||
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
|
||||
#
|
||||
# Type: avrdude -c ?
|
||||
# to get a full listing.
|
||||
#
|
||||
AVRDUDE_PROGRAMMER = stk500
|
||||
|
||||
|
||||
AVRDUDE_PORT = com1 # programmer connected to serial device
|
||||
#AVRDUDE_PORT = lpt1 # programmer connected to parallel port
|
||||
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||
|
||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||
|
||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
||||
# Note that this counter needs to be initialized first using -Yn,
|
||||
# see avrdude manual.
|
||||
#AVRDUDE_ERASE += -y
|
||||
|
||||
# Uncomment the following if you do /not/ wish a verification to be
|
||||
# performed after programming the device.
|
||||
#AVRDUDE_FLAGS += -V
|
||||
|
||||
# Increase verbosity level. Please use this when submitting bug
|
||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
||||
# to submit bug reports.
|
||||
#AVRDUDE_FLAGS += -v -v
|
||||
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Define directories, if needed.
|
||||
DIRAVR = c:/winavr
|
||||
DIRAVRBIN = $(DIRAVR)/bin
|
||||
DIRAVRUTILS = $(DIRAVR)/utils/bin
|
||||
DIRINC = .
|
||||
DIRLIB = $(DIRAVR)/avr/lib
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
SHELL = sh
|
||||
|
||||
CC = avr-gcc
|
||||
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
SIZE = avr-size
|
||||
|
||||
|
||||
# Programming support using avrdude.
|
||||
AVRDUDE = avrdude
|
||||
|
||||
|
||||
REMOVE = rm -f
|
||||
COPY = cp
|
||||
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
ELFSIZE = $(SIZE) -A $(TARGET).elf
|
||||
|
||||
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = -------- begin --------
|
||||
MSG_END = -------- end --------
|
||||
MSG_SIZE_BEFORE = Size before:
|
||||
MSG_SIZE_AFTER = Size after:
|
||||
MSG_COFF = Converting to AVR COFF:
|
||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
||||
MSG_FLASH = Creating load file for Flash:
|
||||
MSG_EEPROM = Creating load file for EEPROM:
|
||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
||||
MSG_LINKING = Linking:
|
||||
MSG_COMPILING = Compiling:
|
||||
MSG_ASSEMBLING = Assembling:
|
||||
MSG_CLEANING = Cleaning project:
|
||||
|
||||
|
||||
|
||||
|
||||
# Define all object files.
|
||||
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
|
||||
|
||||
# Define all listing files.
|
||||
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
|
||||
|
||||
|
||||
|
||||
# Default target.
|
||||
all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
|
||||
$(TARGET).lss $(TARGET).sym sizeafter finished end
|
||||
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
# the following magic strings to be generated by the compile job.
|
||||
begin:
|
||||
@echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
finished:
|
||||
@echo $(MSG_ERRORS_NONE)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
@echo
|
||||
|
||||
|
||||
# Display size of file.
|
||||
sizebefore:
|
||||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
|
||||
|
||||
sizeafter:
|
||||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
|
||||
|
||||
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in
|
||||
# AVR Studio or VMLAB.
|
||||
COFFCONVERT=$(OBJCOPY) --debugging \
|
||||
--change-section-address .data-0x800000 \
|
||||
--change-section-address .bss-0x800000 \
|
||||
--change-section-address .noinit-0x800000 \
|
||||
--change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
coff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
extcoff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
|
||||
|
||||
|
||||
# Create final output files (.hex, .eep) from ELF output file.
|
||||
%.hex: %.elf
|
||||
@echo
|
||||
@echo $(MSG_FLASH) $@
|
||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||
|
||||
%.eep: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EEPROM) $@
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
%.lss: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
@echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
avr-nm -n $< > $@
|
||||
|
||||
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.elf: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_LINKING) $@
|
||||
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
%.o : %.c
|
||||
@echo
|
||||
@echo $(MSG_COMPILING) $<
|
||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files.
|
||||
%.s : %.c
|
||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
%.o : %.S
|
||||
@echo
|
||||
@echo $(MSG_ASSEMBLING) $<
|
||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list finished end
|
||||
|
||||
clean_list :
|
||||
@echo
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).hex
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).obj
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).obj
|
||||
$(REMOVE) $(TARGET).a90
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lnk
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(OBJ)
|
||||
$(REMOVE) $(LST)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
|
||||
|
||||
# Automatically generate C source code dependencies.
|
||||
# (Code originally taken from the GNU make user manual and modified
|
||||
# (See README.txt Credits).)
|
||||
#
|
||||
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
|
||||
# (see the SHELL variable defined above).
|
||||
# This may not work with other shells or other seds.
|
||||
#
|
||||
%.d: %.c
|
||||
set -e; $(CC) -MM $(ALL_CFLAGS) $< \
|
||||
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
|
||||
# Remove the '-' if you want to see the dependency files generated.
|
||||
-include $(SRC:.c=.d)
|
||||
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
|
||||
clean clean_list program
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
# Makefile to compile and link the I2C Master library and test program
|
||||
#
|
||||
# based on
|
||||
# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
|
||||
#
|
||||
# Note:
|
||||
# The warnings which appear while converting ELF to AVR Extended COFF (make extcoff)
|
||||
# can be ignored
|
||||
#
|
||||
#
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
|
||||
# 4.07 or greater).
|
||||
#
|
||||
# make program = Download the hex file to the device, using avrdude. Please
|
||||
# customize the avrdude settings below first!
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#
|
||||
|
||||
|
||||
# MCU name
|
||||
MCU = at90s8515
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
OPT = s
|
||||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = test_i2cmaster
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c
|
||||
|
||||
# List Assembler source files here.
|
||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
||||
# will not be considered source files but generated files (assembler
|
||||
# output from the compiler), and will be deleted upon "make clean"!
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC = i2cmaster.S
|
||||
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
EXTRAINCDIRS =
|
||||
|
||||
|
||||
# Optional compiler flags.
|
||||
# -g: generate debugging information (for GDB, or for COFF conversion)
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see gcc manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlms: create assembler listing
|
||||
CFLAGS = -g -O$(OPT) \
|
||||
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
|
||||
-Wall -Wstrict-prototypes \
|
||||
-Wa,-adhlns=$(<:.c=.lst) \
|
||||
$(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
|
||||
|
||||
# Set a "language standard" compiler flag.
|
||||
# Unremark just one line below to set the language standard to use.
|
||||
# gnu99 = C99 + GNU extensions. See GCC manual for more information.
|
||||
#CFLAGS += -std=c89
|
||||
#CFLAGS += -std=gnu89
|
||||
#CFLAGS += -std=c99
|
||||
CFLAGS += -std=gnu99
|
||||
|
||||
|
||||
|
||||
# Optional assembler flags.
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlms: create listing
|
||||
# -gstabs: have the assembler create line number information; note that
|
||||
# for use in COFF files, additional information about filenames
|
||||
# and function names needs to be present in the assembler source
|
||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
||||
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
|
||||
|
||||
|
||||
|
||||
# Optional linker flags.
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
||||
|
||||
|
||||
|
||||
# Additional libraries
|
||||
|
||||
# Minimalistic printf version
|
||||
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
|
||||
|
||||
# Floating point printf version (requires -lm below)
|
||||
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
|
||||
|
||||
# -lm = math library
|
||||
LDFLAGS += -lm
|
||||
|
||||
|
||||
|
||||
|
||||
# Programming support using avrdude. Settings and variables.
|
||||
|
||||
# Programming hardware: alf avr910 avrisp bascom bsd
|
||||
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
|
||||
#
|
||||
# Type: avrdude -c ?
|
||||
# to get a full listing.
|
||||
#
|
||||
AVRDUDE_PROGRAMMER = stk500
|
||||
|
||||
|
||||
AVRDUDE_PORT = com1 # programmer connected to serial device
|
||||
#AVRDUDE_PORT = lpt1 # programmer connected to parallel port
|
||||
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||
|
||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||
|
||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
||||
# Note that this counter needs to be initialized first using -Yn,
|
||||
# see avrdude manual.
|
||||
#AVRDUDE_ERASE += -y
|
||||
|
||||
# Uncomment the following if you do /not/ wish a verification to be
|
||||
# performed after programming the device.
|
||||
#AVRDUDE_FLAGS += -V
|
||||
|
||||
# Increase verbosity level. Please use this when submitting bug
|
||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
||||
# to submit bug reports.
|
||||
#AVRDUDE_FLAGS += -v -v
|
||||
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Define directories, if needed.
|
||||
DIRAVR = c:/winavr
|
||||
DIRAVRBIN = $(DIRAVR)/bin
|
||||
DIRAVRUTILS = $(DIRAVR)/utils/bin
|
||||
DIRINC = .
|
||||
DIRLIB = $(DIRAVR)/avr/lib
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
SHELL = sh
|
||||
|
||||
CC = avr-gcc
|
||||
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
SIZE = avr-size
|
||||
|
||||
|
||||
# Programming support using avrdude.
|
||||
AVRDUDE = avrdude
|
||||
|
||||
|
||||
REMOVE = rm -f
|
||||
COPY = cp
|
||||
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
ELFSIZE = $(SIZE) -A $(TARGET).elf
|
||||
|
||||
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = -------- begin --------
|
||||
MSG_END = -------- end --------
|
||||
MSG_SIZE_BEFORE = Size before:
|
||||
MSG_SIZE_AFTER = Size after:
|
||||
MSG_COFF = Converting to AVR COFF:
|
||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
||||
MSG_FLASH = Creating load file for Flash:
|
||||
MSG_EEPROM = Creating load file for EEPROM:
|
||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
||||
MSG_LINKING = Linking:
|
||||
MSG_COMPILING = Compiling:
|
||||
MSG_ASSEMBLING = Assembling:
|
||||
MSG_CLEANING = Cleaning project:
|
||||
|
||||
|
||||
|
||||
|
||||
# Define all object files.
|
||||
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
|
||||
|
||||
# Define all listing files.
|
||||
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
|
||||
|
||||
|
||||
|
||||
# Default target.
|
||||
all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
|
||||
$(TARGET).lss $(TARGET).sym sizeafter finished end
|
||||
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
# the following magic strings to be generated by the compile job.
|
||||
begin:
|
||||
@echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
finished:
|
||||
@echo $(MSG_ERRORS_NONE)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
@echo
|
||||
|
||||
|
||||
# Display size of file.
|
||||
sizebefore:
|
||||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
|
||||
|
||||
sizeafter:
|
||||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
|
||||
|
||||
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in
|
||||
# AVR Studio or VMLAB.
|
||||
COFFCONVERT=$(OBJCOPY) --debugging \
|
||||
--change-section-address .data-0x800000 \
|
||||
--change-section-address .bss-0x800000 \
|
||||
--change-section-address .noinit-0x800000 \
|
||||
--change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
coff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
extcoff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
|
||||
|
||||
|
||||
# Create final output files (.hex, .eep) from ELF output file.
|
||||
%.hex: %.elf
|
||||
@echo
|
||||
@echo $(MSG_FLASH) $@
|
||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||
|
||||
%.eep: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EEPROM) $@
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
%.lss: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
@echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
avr-nm -n $< > $@
|
||||
|
||||
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.elf: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_LINKING) $@
|
||||
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
%.o : %.c
|
||||
@echo
|
||||
@echo $(MSG_COMPILING) $<
|
||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files.
|
||||
%.s : %.c
|
||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
%.o : %.S
|
||||
@echo
|
||||
@echo $(MSG_ASSEMBLING) $<
|
||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list finished end
|
||||
|
||||
clean_list :
|
||||
@echo
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).hex
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).obj
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).obj
|
||||
$(REMOVE) $(TARGET).a90
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lnk
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(OBJ)
|
||||
$(REMOVE) $(LST)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
|
||||
|
||||
# Automatically generate C source code dependencies.
|
||||
# (Code originally taken from the GNU make user manual and modified
|
||||
# (See README.txt Credits).)
|
||||
#
|
||||
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
|
||||
# (see the SHELL variable defined above).
|
||||
# This may not work with other shells or other seds.
|
||||
#
|
||||
%.d: %.c
|
||||
set -e; $(CC) -MM $(ALL_CFLAGS) $< \
|
||||
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
|
||||
# Remove the '-' if you want to see the dependency files generated.
|
||||
-include $(SRC:.c=.d)
|
||||
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
|
||||
clean clean_list program
|
||||
|
|
@ -0,0 +1,502 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# Makefile to compile and link the TWImaster library and test program
|
||||
# Author: Peter Fleury
|
||||
# File: $Id: makefile.twimaster,v 1.1 2005/03/29 14:50:05 Peter Exp $
|
||||
# based on WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
|
||||
#
|
||||
# Adjust F_CPU below to the clock frequency in Mhz of your AVR target
|
||||
#
|
||||
# rename this file to "makefile" or invoke with "make -f makefile.twimaster"
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF.
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF.
|
||||
#
|
||||
# make program = Download the hex file to the device, using avrdude.
|
||||
# Please customize the avrdude settings below first!
|
||||
#
|
||||
# make debug = Start either simulavr or avarice as specified for debugging,
|
||||
# with avr-gdb or avr-insight as the front end for debugging.
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only.
|
||||
#
|
||||
# make filename.i = Create a preprocessed source file for use in submitting
|
||||
# bug reports to the GCC project.
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# MCU name
|
||||
MCU = atmega8
|
||||
|
||||
|
||||
# Processor frequency.
|
||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||
# processor frequency. You can then use this symbol in your source code to
|
||||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
|
||||
# automatically to create a 32-bit value in your source code.
|
||||
F_CPU = 4000000
|
||||
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = test_i2cmaster
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c twimaster.c
|
||||
|
||||
|
||||
# List Assembler source files here.
|
||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
||||
# will not be considered source files but generated files (assembler
|
||||
# output from the compiler), and will be deleted upon "make clean"!
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC =
|
||||
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
# 0 = turn off optimization. s = optimize for size.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
OPT = s
|
||||
|
||||
|
||||
# Debugging format.
|
||||
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
|
||||
# AVR Studio 4.10 requires dwarf-2.
|
||||
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
|
||||
DEBUG = dwarf-2
|
||||
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
# Use forward slashes for directory separators.
|
||||
# For a directory that has spaces, enclose it in quotes.
|
||||
EXTRAINCDIRS =
|
||||
|
||||
|
||||
# Compiler flag to set the C Standard level.
|
||||
# c89 = "ANSI" C
|
||||
# gnu89 = c89 plus GCC extensions
|
||||
# c99 = ISO C99 standard (not yet fully implemented)
|
||||
# gnu99 = c99 plus GCC extensions
|
||||
CSTANDARD = -std=gnu99
|
||||
|
||||
|
||||
# Place -D or -U options here
|
||||
CDEFS = -DF_CPU=$(F_CPU)UL
|
||||
|
||||
|
||||
# Place -I options here
|
||||
CINCS =
|
||||
|
||||
|
||||
|
||||
#---------------- Compiler Options ----------------
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CFLAGS = -g$(DEBUG)
|
||||
CFLAGS += $(CDEFS) $(CINCS)
|
||||
CFLAGS += -O$(OPT)
|
||||
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||
CFLAGS += -Wall -Wstrict-prototypes
|
||||
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
|
||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
CFLAGS += $(CSTANDARD)
|
||||
|
||||
|
||||
#---------------- Assembler Options ----------------
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlms: create listing
|
||||
# -gstabs: have the assembler create line number information; note that
|
||||
# for use in COFF files, additional information about filenames
|
||||
# and function names needs to be present in the assembler source
|
||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
||||
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
|
||||
|
||||
|
||||
#---------------- Library Options ----------------
|
||||
# Minimalistic printf version
|
||||
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
|
||||
|
||||
# Floating point printf version (requires MATH_LIB = -lm below)
|
||||
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
|
||||
|
||||
# If this is left blank, then it will use the Standard printf version.
|
||||
PRINTF_LIB =
|
||||
#PRINTF_LIB = $(PRINTF_LIB_MIN)
|
||||
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
|
||||
|
||||
|
||||
# Minimalistic scanf version
|
||||
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
|
||||
|
||||
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
|
||||
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
|
||||
|
||||
# If this is left blank, then it will use the Standard scanf version.
|
||||
SCANF_LIB =
|
||||
#SCANF_LIB = $(SCANF_LIB_MIN)
|
||||
#SCANF_LIB = $(SCANF_LIB_FLOAT)
|
||||
|
||||
|
||||
MATH_LIB = -lm
|
||||
|
||||
|
||||
|
||||
#---------------- External Memory Options ----------------
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# used for variables (.data/.bss) and heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# only used for heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
EXTMEMOPTS =
|
||||
|
||||
|
||||
|
||||
#---------------- Linker Options ----------------
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
||||
LDFLAGS += $(EXTMEMOPTS)
|
||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
|
||||
|
||||
|
||||
|
||||
#---------------- Programming Options (avrdude) ----------------
|
||||
|
||||
# Programming hardware: alf avr910 avrisp bascom bsd
|
||||
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
|
||||
#
|
||||
# Type: avrdude -c ?
|
||||
# to get a full listing.
|
||||
#
|
||||
AVRDUDE_PROGRAMMER = stk500
|
||||
|
||||
# com1 = serial port. Use lpt1 to connect to parallel port.
|
||||
AVRDUDE_PORT = com1 # programmer connected to serial device
|
||||
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||
|
||||
|
||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
||||
# Note that this counter needs to be initialized first using -Yn,
|
||||
# see avrdude manual.
|
||||
#AVRDUDE_ERASE_COUNTER = -y
|
||||
|
||||
# Uncomment the following if you do /not/ wish a verification to be
|
||||
# performed after programming the device.
|
||||
#AVRDUDE_NO_VERIFY = -V
|
||||
|
||||
# Increase verbosity level. Please use this when submitting bug
|
||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
||||
# to submit bug reports.
|
||||
#AVRDUDE_VERBOSE = -v -v
|
||||
|
||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
|
||||
|
||||
|
||||
|
||||
#---------------- Debugging Options ----------------
|
||||
|
||||
# For simulavr only - target MCU frequency.
|
||||
DEBUG_MFREQ = $(F_CPU)
|
||||
|
||||
# Set the DEBUG_UI to either gdb or insight.
|
||||
# DEBUG_UI = gdb
|
||||
DEBUG_UI = insight
|
||||
|
||||
# Set the debugging back-end to either avarice, simulavr.
|
||||
DEBUG_BACKEND = avarice
|
||||
#DEBUG_BACKEND = simulavr
|
||||
|
||||
# GDB Init Filename.
|
||||
GDBINIT_FILE = __avr_gdbinit
|
||||
|
||||
# When using avarice settings for the JTAG
|
||||
JTAG_DEV = /dev/com1
|
||||
|
||||
# Debugging port used to communicate between GDB / avarice / simulavr.
|
||||
DEBUG_PORT = 4242
|
||||
|
||||
# Debugging host used to communicate between GDB / avarice / simulavr, normally
|
||||
# just set to localhost unless doing some sort of crazy debugging when
|
||||
# avarice is running on a different computer.
|
||||
DEBUG_HOST = localhost
|
||||
|
||||
|
||||
|
||||
#============================================================================
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
SHELL = sh
|
||||
CC = avr-gcc
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
SIZE = avr-size
|
||||
NM = avr-nm
|
||||
AVRDUDE = avrdude
|
||||
REMOVE = rm -f
|
||||
COPY = cp
|
||||
WINSHELL = cmd
|
||||
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = -------- begin --------
|
||||
MSG_END = -------- end --------
|
||||
MSG_SIZE_BEFORE = Size before:
|
||||
MSG_SIZE_AFTER = Size after:
|
||||
MSG_COFF = Converting to AVR COFF:
|
||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
||||
MSG_FLASH = Creating load file for Flash:
|
||||
MSG_EEPROM = Creating load file for EEPROM:
|
||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
||||
MSG_LINKING = Linking:
|
||||
MSG_COMPILING = Compiling:
|
||||
MSG_ASSEMBLING = Assembling:
|
||||
MSG_CLEANING = Cleaning project:
|
||||
|
||||
|
||||
|
||||
|
||||
# Define all object files.
|
||||
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
|
||||
|
||||
# Define all listing files.
|
||||
LST = $(SRC:.c=.lst) $(ASRC:.S=.lst)
|
||||
|
||||
|
||||
# Compiler flags to generate dependency files.
|
||||
GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
|
||||
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Default target.
|
||||
all: begin gccversion sizebefore build sizeafter end
|
||||
|
||||
build: elf hex eep lss sym
|
||||
|
||||
elf: $(TARGET).elf
|
||||
hex: $(TARGET).hex
|
||||
eep: $(TARGET).eep
|
||||
lss: $(TARGET).lss
|
||||
sym: $(TARGET).sym
|
||||
|
||||
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
# the following magic strings to be generated by the compile job.
|
||||
begin:
|
||||
@echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
@echo
|
||||
|
||||
|
||||
# Display size of file.
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
ELFSIZE = $(SIZE) -A $(TARGET).elf
|
||||
AVRMEM = avr-mem.sh $(TARGET).elf $(MCU)
|
||||
|
||||
sizebefore:
|
||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
|
||||
$(AVRMEM) 2>/dev/null; echo; fi
|
||||
|
||||
sizeafter:
|
||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
|
||||
$(AVRMEM) 2>/dev/null; echo; fi
|
||||
|
||||
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
|
||||
# Generate avr-gdb config/init file which does the following:
|
||||
# define the reset signal, load the target file, connect to target, and set
|
||||
# a breakpoint at main().
|
||||
gdb-config:
|
||||
@$(REMOVE) $(GDBINIT_FILE)
|
||||
@echo define reset >> $(GDBINIT_FILE)
|
||||
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
|
||||
@echo end >> $(GDBINIT_FILE)
|
||||
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
|
||||
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
|
||||
ifeq ($(DEBUG_BACKEND),simulavr)
|
||||
@echo load >> $(GDBINIT_FILE)
|
||||
endif
|
||||
@echo break main >> $(GDBINIT_FILE)
|
||||
|
||||
debug: gdb-config $(TARGET).elf
|
||||
ifeq ($(DEBUG_BACKEND), avarice)
|
||||
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
|
||||
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
|
||||
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
|
||||
@$(WINSHELL) /c pause
|
||||
|
||||
else
|
||||
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
|
||||
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
|
||||
endif
|
||||
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
|
||||
|
||||
|
||||
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
|
||||
COFFCONVERT=$(OBJCOPY) --debugging \
|
||||
--change-section-address .data-0x800000 \
|
||||
--change-section-address .bss-0x800000 \
|
||||
--change-section-address .noinit-0x800000 \
|
||||
--change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
coff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
extcoff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
|
||||
# Create final output files (.hex, .eep) from ELF output file.
|
||||
%.hex: %.elf
|
||||
@echo
|
||||
@echo $(MSG_FLASH) $@
|
||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||
|
||||
%.eep: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EEPROM) $@
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
%.lss: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
@echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
$(NM) -n $< > $@
|
||||
|
||||
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.elf: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_LINKING) $@
|
||||
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
%.o : %.c
|
||||
@echo
|
||||
@echo $(MSG_COMPILING) $<
|
||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files.
|
||||
%.s : %.c
|
||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
%.o : %.S
|
||||
@echo
|
||||
@echo $(MSG_ASSEMBLING) $<
|
||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
# Create preprocessed source for use in sending a bug report.
|
||||
%.i : %.c
|
||||
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list end
|
||||
|
||||
clean_list :
|
||||
@echo
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).hex
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(OBJ)
|
||||
$(REMOVE) $(LST)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
$(REMOVE) .dep/*
|
||||
|
||||
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all begin finish end sizebefore sizeafter gccversion \
|
||||
build elf hex eep lss sym coff extcoff \
|
||||
clean clean_list program debug gdb-config
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/****************************************************************************
|
||||
Title: Access serial EEPROM 24C02 using I2C interace
|
||||
Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||||
File: $Id: test_i2cmaster.c,v 1.2 2003/12/06 17:07:18 peter Exp $
|
||||
Software: AVR-GCC 3.3
|
||||
Hardware: AT90S8515 at 4 Mhz, any AVR device can be used
|
||||
|
||||
Description:
|
||||
This example shows how the I2C library i2cmaster.S can be used to
|
||||
access a serial eeprom.
|
||||
Based on Atmel Application Note AVR300, adapted to AVR-GCC C interface
|
||||
|
||||
*****************************************************************************/
|
||||
#include <avr/io.h>
|
||||
#include "i2cmaster.h"
|
||||
|
||||
|
||||
#define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned char ret;
|
||||
|
||||
|
||||
DDRB = 0xff; // use all pins on port B for output
|
||||
PORTB = 0xff; // (active low LED's )
|
||||
|
||||
i2c_init(); // init I2C interface
|
||||
|
||||
/* write 0x75 to eeprom address 0x05 (Byte Write) */
|
||||
ret = i2c_start(Dev24C02+I2C_WRITE); // set device address and write mode
|
||||
if ( ret ) {
|
||||
/* failed to issue start condition, possibly no device found */
|
||||
i2c_stop();
|
||||
PORTB=0x00; // activate all 8 LED to show error */
|
||||
}else {
|
||||
/* issuing start condition ok, device accessible */
|
||||
i2c_write(0x05); // write address = 5
|
||||
i2c_write(0x75); // ret=0 -> Ok, ret=1 -> no ACK
|
||||
i2c_stop(); // set stop conditon = release bus
|
||||
|
||||
/* write ok, read value back from eeprom address 0x05, wait until
|
||||
the device is no longer busy from the previous write operation */
|
||||
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
|
||||
i2c_write(0x05); // write address = 5
|
||||
i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode
|
||||
ret = i2c_readNak(); // read one byte
|
||||
i2c_stop();
|
||||
|
||||
PORTB = ~ret; // output byte on the LED's
|
||||
|
||||
/* write 0x70,0x71,072,073 to eeprom address 0x00..0x03 (Page Write),
|
||||
wait until the device is no longer busy from the previous write operation */
|
||||
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
|
||||
i2c_write(0x00); // write start address = 0
|
||||
i2c_write(0x70); // write data to address 0
|
||||
i2c_write(0x71); // " " " " 1
|
||||
i2c_write(0x72); // " " " " 2
|
||||
i2c_write(0x74); // " " " " 3
|
||||
i2c_stop(); // set stop conditon = release bus
|
||||
|
||||
/* write ok, read value back from eeprom address 0..3 (Sequencial Read),
|
||||
wait until the device is no longer busy from the previous write operation */
|
||||
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
|
||||
i2c_write(0x00); // write address = 0
|
||||
i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode
|
||||
ret = i2c_readAck(); // read one byte form address 0
|
||||
ret = i2c_readAck(); // " " " " " 1
|
||||
ret = i2c_readAck(); // " " " " " 2
|
||||
ret = i2c_readNak(); // " " " " " 3
|
||||
i2c_stop(); // set stop condition = release bus
|
||||
|
||||
PORTB = ~ret; // output byte on the LED's
|
||||
}
|
||||
|
||||
for(;;);
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
/*************************************************************************
|
||||
* Title: I2C master library using hardware TWI interface
|
||||
* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||||
* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
|
||||
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
|
||||
* Target: any AVR device with hardware TWI
|
||||
* Usage: API compatible with I2C Software Library i2cmaster.h
|
||||
**************************************************************************/
|
||||
#include <inttypes.h>
|
||||
#include <compat/twi.h>
|
||||
|
||||
#include "i2cmaster.h"
|
||||
|
||||
|
||||
/* define CPU frequency in Mhz here if not defined in Makefile */
|
||||
#ifndef F_CPU
|
||||
#define F_CPU 4000000UL
|
||||
#endif
|
||||
|
||||
/* I2C clock in Hz */
|
||||
#define SCL_CLOCK 400000 // previously set to 100000L ::2012, Ben Blazak::
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Initialization of the I2C bus interface. Need to be called only once
|
||||
*************************************************************************/
|
||||
void i2c_init(void)
|
||||
{
|
||||
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
|
||||
|
||||
TWSR = 0; /* no prescaler */
|
||||
TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
|
||||
|
||||
}/* i2c_init */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Issues a start condition and sends address and transfer direction.
|
||||
return 0 = device accessible, 1= failed to access device
|
||||
*************************************************************************/
|
||||
unsigned char i2c_start(unsigned char address)
|
||||
{
|
||||
uint8_t twst;
|
||||
|
||||
// send START condition
|
||||
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
||||
|
||||
// wait until transmission completed
|
||||
while(!(TWCR & (1<<TWINT)));
|
||||
|
||||
// check value of TWI Status Register. Mask prescaler bits.
|
||||
twst = TW_STATUS & 0xF8;
|
||||
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
|
||||
|
||||
// send device address
|
||||
TWDR = address;
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
|
||||
// wail until transmission completed and ACK/NACK has been received
|
||||
while(!(TWCR & (1<<TWINT)));
|
||||
|
||||
// check value of TWI Status Register. Mask prescaler bits.
|
||||
twst = TW_STATUS & 0xF8;
|
||||
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}/* i2c_start */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Issues a start condition and sends address and transfer direction.
|
||||
If device is busy, use ack polling to wait until device is ready
|
||||
|
||||
Input: address and transfer direction of I2C device
|
||||
*************************************************************************/
|
||||
void i2c_start_wait(unsigned char address)
|
||||
{
|
||||
uint8_t twst;
|
||||
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
// send START condition
|
||||
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
||||
|
||||
// wait until transmission completed
|
||||
while(!(TWCR & (1<<TWINT)));
|
||||
|
||||
// check value of TWI Status Register. Mask prescaler bits.
|
||||
twst = TW_STATUS & 0xF8;
|
||||
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
|
||||
|
||||
// send device address
|
||||
TWDR = address;
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
|
||||
// wail until transmission completed
|
||||
while(!(TWCR & (1<<TWINT)));
|
||||
|
||||
// check value of TWI Status Register. Mask prescaler bits.
|
||||
twst = TW_STATUS & 0xF8;
|
||||
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
|
||||
{
|
||||
/* device busy, send stop condition to terminate write operation */
|
||||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
||||
|
||||
// wait until stop condition is executed and bus released
|
||||
while(TWCR & (1<<TWSTO));
|
||||
|
||||
continue;
|
||||
}
|
||||
//if( twst != TW_MT_SLA_ACK) return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}/* i2c_start_wait */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Issues a repeated start condition and sends address and transfer direction
|
||||
|
||||
Input: address and transfer direction of I2C device
|
||||
|
||||
Return: 0 device accessible
|
||||
1 failed to access device
|
||||
*************************************************************************/
|
||||
unsigned char i2c_rep_start(unsigned char address)
|
||||
{
|
||||
return i2c_start( address );
|
||||
|
||||
}/* i2c_rep_start */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Terminates the data transfer and releases the I2C bus
|
||||
*************************************************************************/
|
||||
void i2c_stop(void)
|
||||
{
|
||||
/* send stop condition */
|
||||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
||||
|
||||
// wait until stop condition is executed and bus released
|
||||
while(TWCR & (1<<TWSTO));
|
||||
|
||||
}/* i2c_stop */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Send one byte to I2C device
|
||||
|
||||
Input: byte to be transfered
|
||||
Return: 0 write successful
|
||||
1 write failed
|
||||
*************************************************************************/
|
||||
unsigned char i2c_write( unsigned char data )
|
||||
{
|
||||
uint8_t twst;
|
||||
|
||||
// send data to the previously addressed device
|
||||
TWDR = data;
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
|
||||
// wait until transmission completed
|
||||
while(!(TWCR & (1<<TWINT)));
|
||||
|
||||
// check value of TWI Status Register. Mask prescaler bits
|
||||
twst = TW_STATUS & 0xF8;
|
||||
if( twst != TW_MT_DATA_ACK) return 1;
|
||||
return 0;
|
||||
|
||||
}/* i2c_write */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Read one byte from the I2C device, request more data from device
|
||||
|
||||
Return: byte read from I2C device
|
||||
*************************************************************************/
|
||||
unsigned char i2c_readAck(void)
|
||||
{
|
||||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
|
||||
while(!(TWCR & (1<<TWINT)));
|
||||
|
||||
return TWDR;
|
||||
|
||||
}/* i2c_readAck */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Read one byte from the I2C device, read is followed by a stop condition
|
||||
|
||||
Return: byte read from I2C device
|
||||
*************************************************************************/
|
||||
unsigned char i2c_readNak(void)
|
||||
{
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
while(!(TWCR & (1<<TWINT)));
|
||||
|
||||
return TWDR;
|
||||
|
||||
}/* i2c_readNak */
|
|
@ -1,10 +1,5 @@
|
|||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#----------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------
|
||||
# Copied from <http://pjrc.com/teensy/blinky.zip>. Modified slightly to work
|
||||
# with <https://github.com/benblazak/ergodox-firmware>.
|
||||
#----------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------
|
||||
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
|
||||
#
|
||||
# Released to the Public Domain
|
||||
|
@ -46,11 +41,13 @@
|
|||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = ergodox-firmware
|
||||
TARGET = blinky
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c
|
||||
SRC = $(TARGET).c \
|
||||
usb_debug_only.c \
|
||||
print.c
|
||||
|
||||
# MCU name, you MUST set this to match the board you are using
|
||||
# type "make clean" after changing this, so all files will be rebuilt
|
|
@ -0,0 +1,159 @@
|
|||
/* LED Blink Example with USB Debug Channel for Teensy USB Development Board
|
||||
* http://www.pjrc.com/teensy/
|
||||
* Copyright (c) 2008, 2010 PJRC.COM, LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
#include "usb_debug_only.h"
|
||||
#include "print.h"
|
||||
|
||||
|
||||
// Teensy 2.0: LED is active high
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB1286__)
|
||||
#define LED_ON (PORTD |= (1<<6))
|
||||
#define LED_OFF (PORTD &= ~(1<<6))
|
||||
|
||||
// Teensy 1.0: LED is active low
|
||||
#else
|
||||
#define LED_ON (PORTD &= ~(1<<6))
|
||||
#define LED_OFF (PORTD |= (1<<6))
|
||||
#endif
|
||||
|
||||
#define LED_CONFIG (DDRD |= (1<<6))
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define DIT 80 /* unit time for morse code */
|
||||
|
||||
void morse_character(char c);
|
||||
void morse_P(const char *s);
|
||||
const unsigned char morse_code_table[];
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
// set for 16 MHz clock, and make sure the LED is off
|
||||
CPU_PRESCALE(0);
|
||||
LED_CONFIG;
|
||||
LED_OFF;
|
||||
|
||||
// initialize the USB, but don't want for the host to
|
||||
// configure. The first several messages sent will be
|
||||
// lost because the PC hasn't configured the USB yet,
|
||||
// but we care more about blinking than debug messages!
|
||||
usb_init();
|
||||
|
||||
// blink morse code messages!
|
||||
while (1) {
|
||||
for (i=0; i<6; i++) {
|
||||
morse_P(PSTR("SOS"));
|
||||
_delay_ms(1500);
|
||||
}
|
||||
morse_P(PSTR("DOES ANYBODY STILL KNOW MORSE CODE?"));
|
||||
_delay_ms(4000);
|
||||
}
|
||||
}
|
||||
|
||||
// blink a single character in Morse code
|
||||
void morse_character(char c)
|
||||
{
|
||||
unsigned char code, count;
|
||||
|
||||
if (c == ' ') {
|
||||
print("Space\n");
|
||||
_delay_ms(DIT * 7);
|
||||
return;
|
||||
}
|
||||
if (c < 'A' || c > 'Z') {
|
||||
print("Opps, unsupported character: ");
|
||||
pchar(c);
|
||||
print("\n");
|
||||
return;
|
||||
}
|
||||
print("Char ");
|
||||
pchar(c);
|
||||
pchar(':');
|
||||
code = pgm_read_byte(morse_code_table + (c - 'A'));
|
||||
for (count = code & 0x07; count > 0; count--) {
|
||||
LED_ON;
|
||||
if (code & 0x80) {
|
||||
print(" dah");
|
||||
_delay_ms(DIT * 3);
|
||||
} else {
|
||||
print(" dit");
|
||||
_delay_ms(DIT);
|
||||
}
|
||||
LED_OFF;
|
||||
_delay_ms(DIT);
|
||||
code = code << 1;
|
||||
}
|
||||
print("\n");
|
||||
_delay_ms(DIT * 2);
|
||||
}
|
||||
|
||||
// blink an entire message in Morse code
|
||||
// the string must be in flash memory (using PSTR macro)
|
||||
void morse_P(const char *s)
|
||||
{
|
||||
char c;
|
||||
|
||||
while (1) {
|
||||
c = pgm_read_byte(s++);
|
||||
if (!c) break;
|
||||
morse_character(c);
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
|
||||
// lookup table for all 26 letters. Upper 5 bits are the pulses
|
||||
// to send (MSB first), and the lower 3 bits are the number of
|
||||
// bits to send for this letter.
|
||||
const unsigned char PROGMEM morse_code_table[] = {
|
||||
0x40 + 2, // A: .-
|
||||
0x80 + 4, // B: -...
|
||||
0xA0 + 4, // C: -.-.
|
||||
0x80 + 3, // D: -..
|
||||
0x00 + 1, // E: .
|
||||
0x20 + 4, // F: ..-.
|
||||
0xC0 + 3, // G: --.
|
||||
0x00 + 4, // H: ....
|
||||
0x00 + 2, // I: ..
|
||||
0x70 + 4, // J: .---
|
||||
0xA0 + 3, // K: -.-
|
||||
0x40 + 4, // L: .-..
|
||||
0xC0 + 2, // M: --
|
||||
0x80 + 2, // N: -.
|
||||
0xE0 + 3, // O: ---
|
||||
0x60 + 4, // P: .--.
|
||||
0xD0 + 4, // Q: --.-
|
||||
0x40 + 3, // R: .-.
|
||||
0x00 + 3, // S: ...
|
||||
0x80 + 1, // T: -
|
||||
0x20 + 3, // U: ..-
|
||||
0x10 + 4, // V: ...-
|
||||
0x60 + 3, // W: .--
|
||||
0x90 + 4, // X: -..-
|
||||
0xB0 + 4, // Y: -.--
|
||||
0xC0 + 4 // Z: --..
|
||||
};
|
||||
|
|
@ -0,0 +1,614 @@
|
|||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#----------------------------------------------------------------------------
|
||||
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
|
||||
#
|
||||
# Released to the Public Domain
|
||||
#
|
||||
# Additional material for this makefile was written by:
|
||||
# Peter Fleury
|
||||
# Tim Henigan
|
||||
# Colin O'Flynn
|
||||
# Reiner Patommel
|
||||
# Markus Pfaff
|
||||
# Sander Pool
|
||||
# Frederik Rouleau
|
||||
# Carlos Lamas
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF.
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF.
|
||||
#
|
||||
# make program = Download the hex file to the device, using avrdude.
|
||||
# Please customize the avrdude settings below first!
|
||||
#
|
||||
# make debug = Start either simulavr or avarice as specified for debugging,
|
||||
# with avr-gdb or avr-insight as the front end for debugging.
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only.
|
||||
#
|
||||
# make filename.i = Create a preprocessed source file for use in submitting
|
||||
# bug reports to the GCC project.
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = example
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c \
|
||||
usb_keyboard.c
|
||||
|
||||
|
||||
# MCU name, you MUST set this to match the board you are using
|
||||
# type "make clean" after changing this, so all files will be rebuilt
|
||||
#
|
||||
#MCU = at90usb162 # Teensy 1.0
|
||||
MCU = atmega32u4 # Teensy 2.0
|
||||
#MCU = at90usb646 # Teensy++ 1.0
|
||||
#MCU = at90usb1286 # Teensy++ 2.0
|
||||
|
||||
|
||||
# Processor frequency.
|
||||
# Normally the first thing your program should do is set the clock prescaler,
|
||||
# so your program will run at the correct speed. You should also set this
|
||||
# variable to same clock speed. The _delay_ms() macro uses this, and many
|
||||
# examples use this variable to calculate timings. Do not add a "UL" here.
|
||||
F_CPU = 16000000
|
||||
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
|
||||
# Object files directory
|
||||
# To put object files in current directory, use a dot (.), do NOT make
|
||||
# this an empty or blank macro!
|
||||
OBJDIR = .
|
||||
|
||||
|
||||
# List C++ source files here. (C dependencies are automatically generated.)
|
||||
CPPSRC =
|
||||
|
||||
|
||||
# List Assembler source files here.
|
||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
||||
# will not be considered source files but generated files (assembler
|
||||
# output from the compiler), and will be deleted upon "make clean"!
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC =
|
||||
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
# 0 = turn off optimization. s = optimize for size.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
OPT = s
|
||||
|
||||
|
||||
# Debugging format.
|
||||
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
|
||||
# AVR Studio 4.10 requires dwarf-2.
|
||||
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
|
||||
DEBUG = dwarf-2
|
||||
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
# Use forward slashes for directory separators.
|
||||
# For a directory that has spaces, enclose it in quotes.
|
||||
EXTRAINCDIRS =
|
||||
|
||||
|
||||
# Compiler flag to set the C Standard level.
|
||||
# c89 = "ANSI" C
|
||||
# gnu89 = c89 plus GCC extensions
|
||||
# c99 = ISO C99 standard (not yet fully implemented)
|
||||
# gnu99 = c99 plus GCC extensions
|
||||
CSTANDARD = -std=gnu99
|
||||
|
||||
|
||||
# Place -D or -U options here for C sources
|
||||
CDEFS = -DF_CPU=$(F_CPU)UL
|
||||
|
||||
|
||||
# Place -D or -U options here for ASM sources
|
||||
ADEFS = -DF_CPU=$(F_CPU)
|
||||
|
||||
|
||||
# Place -D or -U options here for C++ sources
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL
|
||||
#CPPDEFS += -D__STDC_LIMIT_MACROS
|
||||
#CPPDEFS += -D__STDC_CONSTANT_MACROS
|
||||
|
||||
|
||||
|
||||
#---------------- Compiler Options C ----------------
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CFLAGS = -g$(DEBUG)
|
||||
CFLAGS += $(CDEFS)
|
||||
CFLAGS += -O$(OPT)
|
||||
CFLAGS += -funsigned-char
|
||||
CFLAGS += -funsigned-bitfields
|
||||
CFLAGS += -ffunction-sections
|
||||
CFLAGS += -fpack-struct
|
||||
CFLAGS += -fshort-enums
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
#CFLAGS += -mshort-calls
|
||||
#CFLAGS += -fno-unit-at-a-time
|
||||
#CFLAGS += -Wundef
|
||||
#CFLAGS += -Wunreachable-code
|
||||
#CFLAGS += -Wsign-compare
|
||||
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
|
||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
CFLAGS += $(CSTANDARD)
|
||||
|
||||
|
||||
#---------------- Compiler Options C++ ----------------
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CPPFLAGS = -g$(DEBUG)
|
||||
CPPFLAGS += $(CPPDEFS)
|
||||
CPPFLAGS += -O$(OPT)
|
||||
CPPFLAGS += -funsigned-char
|
||||
CPPFLAGS += -funsigned-bitfields
|
||||
CPPFLAGS += -fpack-struct
|
||||
CPPFLAGS += -fshort-enums
|
||||
CPPFLAGS += -fno-exceptions
|
||||
CPPFLAGS += -Wall
|
||||
CPPFLAGS += -Wundef
|
||||
#CPPFLAGS += -mshort-calls
|
||||
#CPPFLAGS += -fno-unit-at-a-time
|
||||
#CPPFLAGS += -Wstrict-prototypes
|
||||
#CPPFLAGS += -Wunreachable-code
|
||||
#CPPFLAGS += -Wsign-compare
|
||||
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
|
||||
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
#CPPFLAGS += $(CSTANDARD)
|
||||
|
||||
|
||||
#---------------- Assembler Options ----------------
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns: create listing
|
||||
# -gstabs: have the assembler create line number information; note that
|
||||
# for use in COFF files, additional information about filenames
|
||||
# and function names needs to be present in the assembler source
|
||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
||||
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
|
||||
# dump that will be displayed for a given single line of source input.
|
||||
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
|
||||
|
||||
|
||||
#---------------- Library Options ----------------
|
||||
# Minimalistic printf version
|
||||
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
|
||||
|
||||
# Floating point printf version (requires MATH_LIB = -lm below)
|
||||
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
|
||||
|
||||
# If this is left blank, then it will use the Standard printf version.
|
||||
PRINTF_LIB =
|
||||
#PRINTF_LIB = $(PRINTF_LIB_MIN)
|
||||
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
|
||||
|
||||
|
||||
# Minimalistic scanf version
|
||||
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
|
||||
|
||||
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
|
||||
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
|
||||
|
||||
# If this is left blank, then it will use the Standard scanf version.
|
||||
SCANF_LIB =
|
||||
#SCANF_LIB = $(SCANF_LIB_MIN)
|
||||
#SCANF_LIB = $(SCANF_LIB_FLOAT)
|
||||
|
||||
|
||||
MATH_LIB = -lm
|
||||
|
||||
|
||||
# List any extra directories to look for libraries here.
|
||||
# Each directory must be seperated by a space.
|
||||
# Use forward slashes for directory separators.
|
||||
# For a directory that has spaces, enclose it in quotes.
|
||||
EXTRALIBDIRS =
|
||||
|
||||
|
||||
|
||||
#---------------- External Memory Options ----------------
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# used for variables (.data/.bss) and heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# only used for heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
EXTMEMOPTS =
|
||||
|
||||
|
||||
|
||||
#---------------- Linker Options ----------------
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
||||
LDFLAGS += -Wl,--relax
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
LDFLAGS += $(EXTMEMOPTS)
|
||||
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
|
||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
|
||||
#LDFLAGS += -T linker_script.x
|
||||
|
||||
|
||||
|
||||
#---------------- Programming Options (avrdude) ----------------
|
||||
|
||||
# Programming hardware
|
||||
# Type: avrdude -c ?
|
||||
# to get a full listing.
|
||||
#
|
||||
AVRDUDE_PROGRAMMER = stk500v2
|
||||
|
||||
# com1 = serial port. Use lpt1 to connect to parallel port.
|
||||
AVRDUDE_PORT = com1 # programmer connected to serial device
|
||||
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||
|
||||
|
||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
||||
# Note that this counter needs to be initialized first using -Yn,
|
||||
# see avrdude manual.
|
||||
#AVRDUDE_ERASE_COUNTER = -y
|
||||
|
||||
# Uncomment the following if you do /not/ wish a verification to be
|
||||
# performed after programming the device.
|
||||
#AVRDUDE_NO_VERIFY = -V
|
||||
|
||||
# Increase verbosity level. Please use this when submitting bug
|
||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
||||
# to submit bug reports.
|
||||
#AVRDUDE_VERBOSE = -v -v
|
||||
|
||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
|
||||
|
||||
|
||||
|
||||
#---------------- Debugging Options ----------------
|
||||
|
||||
# For simulavr only - target MCU frequency.
|
||||
DEBUG_MFREQ = $(F_CPU)
|
||||
|
||||
# Set the DEBUG_UI to either gdb or insight.
|
||||
# DEBUG_UI = gdb
|
||||
DEBUG_UI = insight
|
||||
|
||||
# Set the debugging back-end to either avarice, simulavr.
|
||||
DEBUG_BACKEND = avarice
|
||||
#DEBUG_BACKEND = simulavr
|
||||
|
||||
# GDB Init Filename.
|
||||
GDBINIT_FILE = __avr_gdbinit
|
||||
|
||||
# When using avarice settings for the JTAG
|
||||
JTAG_DEV = /dev/com1
|
||||
|
||||
# Debugging port used to communicate between GDB / avarice / simulavr.
|
||||
DEBUG_PORT = 4242
|
||||
|
||||
# Debugging host used to communicate between GDB / avarice / simulavr, normally
|
||||
# just set to localhost unless doing some sort of crazy debugging when
|
||||
# avarice is running on a different computer.
|
||||
DEBUG_HOST = localhost
|
||||
|
||||
|
||||
|
||||
#============================================================================
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
SHELL = sh
|
||||
CC = avr-gcc
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
SIZE = avr-size
|
||||
AR = avr-ar rcs
|
||||
NM = avr-nm
|
||||
AVRDUDE = avrdude
|
||||
REMOVE = rm -f
|
||||
REMOVEDIR = rm -rf
|
||||
COPY = cp
|
||||
WINSHELL = cmd
|
||||
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = -------- begin --------
|
||||
MSG_END = -------- end --------
|
||||
MSG_SIZE_BEFORE = Size before:
|
||||
MSG_SIZE_AFTER = Size after:
|
||||
MSG_COFF = Converting to AVR COFF:
|
||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
||||
MSG_FLASH = Creating load file for Flash:
|
||||
MSG_EEPROM = Creating load file for EEPROM:
|
||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
||||
MSG_LINKING = Linking:
|
||||
MSG_COMPILING = Compiling C:
|
||||
MSG_COMPILING_CPP = Compiling C++:
|
||||
MSG_ASSEMBLING = Assembling:
|
||||
MSG_CLEANING = Cleaning project:
|
||||
MSG_CREATING_LIBRARY = Creating library:
|
||||
|
||||
|
||||
|
||||
|
||||
# Define all object files.
|
||||
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
|
||||
|
||||
# Define all listing files.
|
||||
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
|
||||
|
||||
|
||||
# Compiler flags to generate dependency files.
|
||||
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
|
||||
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
|
||||
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Default target.
|
||||
all: begin gccversion sizebefore build sizeafter end
|
||||
|
||||
# Change the build target to build a HEX file or a library.
|
||||
build: elf hex eep lss sym
|
||||
#build: lib
|
||||
|
||||
|
||||
elf: $(TARGET).elf
|
||||
hex: $(TARGET).hex
|
||||
eep: $(TARGET).eep
|
||||
lss: $(TARGET).lss
|
||||
sym: $(TARGET).sym
|
||||
LIBNAME=lib$(TARGET).a
|
||||
lib: $(LIBNAME)
|
||||
|
||||
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
# the following magic strings to be generated by the compile job.
|
||||
begin:
|
||||
@echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
@echo
|
||||
|
||||
|
||||
# Display size of file.
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
|
||||
ELFSIZE = $(SIZE) $(TARGET).elf
|
||||
|
||||
sizebefore:
|
||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
|
||||
2>/dev/null; echo; fi
|
||||
|
||||
sizeafter:
|
||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
|
||||
2>/dev/null; echo; fi
|
||||
|
||||
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
|
||||
# Generate avr-gdb config/init file which does the following:
|
||||
# define the reset signal, load the target file, connect to target, and set
|
||||
# a breakpoint at main().
|
||||
gdb-config:
|
||||
@$(REMOVE) $(GDBINIT_FILE)
|
||||
@echo define reset >> $(GDBINIT_FILE)
|
||||
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
|
||||
@echo end >> $(GDBINIT_FILE)
|
||||
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
|
||||
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
|
||||
ifeq ($(DEBUG_BACKEND),simulavr)
|
||||
@echo load >> $(GDBINIT_FILE)
|
||||
endif
|
||||
@echo break main >> $(GDBINIT_FILE)
|
||||
|
||||
debug: gdb-config $(TARGET).elf
|
||||
ifeq ($(DEBUG_BACKEND), avarice)
|
||||
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
|
||||
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
|
||||
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
|
||||
@$(WINSHELL) /c pause
|
||||
|
||||
else
|
||||
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
|
||||
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
|
||||
endif
|
||||
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
|
||||
|
||||
|
||||
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
|
||||
COFFCONVERT = $(OBJCOPY) --debugging
|
||||
COFFCONVERT += --change-section-address .data-0x800000
|
||||
COFFCONVERT += --change-section-address .bss-0x800000
|
||||
COFFCONVERT += --change-section-address .noinit-0x800000
|
||||
COFFCONVERT += --change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
|
||||
coff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
extcoff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
|
||||
# Create final output files (.hex, .eep) from ELF output file.
|
||||
%.hex: %.elf
|
||||
@echo
|
||||
@echo $(MSG_FLASH) $@
|
||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@
|
||||
|
||||
%.eep: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EEPROM) $@
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
%.lss: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -S -z $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
@echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
$(NM) -n $< > $@
|
||||
|
||||
|
||||
|
||||
# Create library from object files.
|
||||
.SECONDARY : $(TARGET).a
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.a: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_CREATING_LIBRARY) $@
|
||||
$(AR) $@ $(OBJ)
|
||||
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.elf: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_LINKING) $@
|
||||
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
$(OBJDIR)/%.o : %.c
|
||||
@echo
|
||||
@echo $(MSG_COMPILING) $<
|
||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create object files from C++ source files.
|
||||
$(OBJDIR)/%.o : %.cpp
|
||||
@echo
|
||||
@echo $(MSG_COMPILING_CPP) $<
|
||||
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files.
|
||||
%.s : %.c
|
||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C++ source files.
|
||||
%.s : %.cpp
|
||||
$(CC) -S $(ALL_CPPFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
$(OBJDIR)/%.o : %.S
|
||||
@echo
|
||||
@echo $(MSG_ASSEMBLING) $<
|
||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Create preprocessed source for use in sending a bug report.
|
||||
%.i : %.c
|
||||
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list end
|
||||
|
||||
clean_list :
|
||||
@echo
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).hex
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
$(REMOVE) $(SRC:.c=.i)
|
||||
$(REMOVEDIR) .dep
|
||||
|
||||
|
||||
# Create object files directory
|
||||
$(shell mkdir $(OBJDIR) 2>/dev/null)
|
||||
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all begin finish end sizebefore sizeafter gccversion \
|
||||
build elf hex eep lss sym coff extcoff \
|
||||
clean clean_list program debug gdb-config
|
|
@ -0,0 +1,124 @@
|
|||
/* Keyboard example for Teensy USB Development Board
|
||||
* http://www.pjrc.com/teensy/usb_keyboard.html
|
||||
* Copyright (c) 2008 PJRC.COM, LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include "usb_keyboard.h"
|
||||
|
||||
#define LED_CONFIG (DDRD |= (1<<6))
|
||||
#define LED_ON (PORTD &= ~(1<<6))
|
||||
#define LED_OFF (PORTD |= (1<<6))
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
|
||||
uint8_t number_keys[10]=
|
||||
{KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9};
|
||||
|
||||
uint16_t idle_count=0;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t b, d, mask, i, reset_idle;
|
||||
uint8_t b_prev=0xFF, d_prev=0xFF;
|
||||
|
||||
// set for 16 MHz clock
|
||||
CPU_PRESCALE(0);
|
||||
|
||||
// Configure all port B and port D pins as inputs with pullup resistors.
|
||||
// See the "Using I/O Pins" page for details.
|
||||
// http://www.pjrc.com/teensy/pins.html
|
||||
DDRD = 0x00;
|
||||
DDRB = 0x00;
|
||||
PORTB = 0xFF;
|
||||
PORTD = 0xFF;
|
||||
|
||||
// Initialize the USB, and then wait for the host to set configuration.
|
||||
// If the Teensy is powered without a PC connected to the USB port,
|
||||
// this will wait forever.
|
||||
usb_init();
|
||||
while (!usb_configured()) /* wait */ ;
|
||||
|
||||
// Wait an extra second for the PC's operating system to load drivers
|
||||
// and do whatever it does to actually be ready for input
|
||||
_delay_ms(1000);
|
||||
|
||||
// Configure timer 0 to generate a timer overflow interrupt every
|
||||
// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock
|
||||
// This demonstrates how to use interrupts to implement a simple
|
||||
// inactivity timeout.
|
||||
TCCR0A = 0x00;
|
||||
TCCR0B = 0x05;
|
||||
TIMSK0 = (1<<TOIE0);
|
||||
|
||||
while (1) {
|
||||
// read all port B and port D pins
|
||||
b = PINB;
|
||||
d = PIND;
|
||||
// check if any pins are low, but were high previously
|
||||
mask = 1;
|
||||
reset_idle = 0;
|
||||
for (i=0; i<8; i++) {
|
||||
if (((b & mask) == 0) && (b_prev & mask) != 0) {
|
||||
usb_keyboard_press(KEY_B, KEY_SHIFT);
|
||||
usb_keyboard_press(number_keys[i], 0);
|
||||
reset_idle = 1;
|
||||
}
|
||||
if (((d & mask) == 0) && (d_prev & mask) != 0) {
|
||||
usb_keyboard_press(KEY_D, KEY_SHIFT);
|
||||
usb_keyboard_press(number_keys[i], 0);
|
||||
reset_idle = 1;
|
||||
}
|
||||
mask = mask << 1;
|
||||
}
|
||||
// if any keypresses were detected, reset the idle counter
|
||||
if (reset_idle) {
|
||||
// variables shared with interrupt routines must be
|
||||
// accessed carefully so the interrupt routine doesn't
|
||||
// try to use the variable in the middle of our access
|
||||
cli();
|
||||
idle_count = 0;
|
||||
sei();
|
||||
}
|
||||
// now the current pins will be the previous, and
|
||||
// wait a short delay so we're not highly sensitive
|
||||
// to mechanical "bounce".
|
||||
b_prev = b;
|
||||
d_prev = d;
|
||||
_delay_ms(2);
|
||||
}
|
||||
}
|
||||
|
||||
// This interrupt routine is run approx 61 times per second.
|
||||
// A very simple inactivity timeout is implemented, where we
|
||||
// will send a space character.
|
||||
ISR(TIMER0_OVF_vect)
|
||||
{
|
||||
idle_count++;
|
||||
if (idle_count > 61 * 8) {
|
||||
idle_count = 0;
|
||||
usb_keyboard_press(KEY_SPACE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,592 @@
|
|||
/* USB Keyboard Example for Teensy USB Development Board
|
||||
* http://www.pjrc.com/teensy/usb_keyboard.html
|
||||
* Copyright (c) 2009 PJRC.COM, LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Version 1.0: Initial Release
|
||||
// Version 1.1: Add support for Teensy 2.0
|
||||
|
||||
#define USB_SERIAL_PRIVATE_INCLUDE
|
||||
#include "usb_keyboard.h"
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Configurable Options
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// You can change these to give your code its own name.
|
||||
#define STR_MANUFACTURER L"MfgName"
|
||||
#define STR_PRODUCT L"Keyboard"
|
||||
|
||||
|
||||
// Mac OS-X and Linux automatically load the correct drivers. On
|
||||
// Windows, even though the driver is supplied by Microsoft, an
|
||||
// INF file is needed to load the driver. These numbers need to
|
||||
// match the INF file.
|
||||
#define VENDOR_ID 0x16C0
|
||||
#define PRODUCT_ID 0x047C
|
||||
|
||||
|
||||
// USB devices are supposed to implment a halt feature, which is
|
||||
// rarely (if ever) used. If you comment this line out, the halt
|
||||
// code will be removed, saving 102 bytes of space (gcc 4.3.0).
|
||||
// This is not strictly USB compliant, but works with all major
|
||||
// operating systems.
|
||||
#define SUPPORT_ENDPOINT_HALT
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Endpoint Buffer Configuration
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#define ENDPOINT0_SIZE 32
|
||||
|
||||
#define KEYBOARD_INTERFACE 0
|
||||
#define KEYBOARD_ENDPOINT 3
|
||||
#define KEYBOARD_SIZE 8
|
||||
#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER
|
||||
|
||||
static const uint8_t PROGMEM endpoint_config_table[] = {
|
||||
0,
|
||||
0,
|
||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Descriptor Data
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// Descriptors are the data that your computer reads when it auto-detects
|
||||
// this USB device (called "enumeration" in USB lingo). The most commonly
|
||||
// changed items are editable at the top of this file. Changing things
|
||||
// in here should only be done by those who've read chapter 9 of the USB
|
||||
// spec and relevant portions of any USB class specifications!
|
||||
|
||||
|
||||
static uint8_t PROGMEM device_descriptor[] = {
|
||||
18, // bLength
|
||||
1, // bDescriptorType
|
||||
0x00, 0x02, // bcdUSB
|
||||
0, // bDeviceClass
|
||||
0, // bDeviceSubClass
|
||||
0, // bDeviceProtocol
|
||||
ENDPOINT0_SIZE, // bMaxPacketSize0
|
||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
|
||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
|
||||
0x00, 0x01, // bcdDevice
|
||||
1, // iManufacturer
|
||||
2, // iProduct
|
||||
0, // iSerialNumber
|
||||
1 // bNumConfigurations
|
||||
};
|
||||
|
||||
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
|
||||
static uint8_t PROGMEM keyboard_hid_report_desc[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x06, // Usage (Keyboard),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x95, 0x08, // Report Count (8),
|
||||
0x05, 0x07, // Usage Page (Key Codes),
|
||||
0x19, 0xE0, // Usage Minimum (224),
|
||||
0x29, 0xE7, // Usage Maximum (231),
|
||||
0x15, 0x00, // Logical Minimum (0),
|
||||
0x25, 0x01, // Logical Maximum (1),
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x75, 0x08, // Report Size (8),
|
||||
0x81, 0x03, // Input (Constant), ;Reserved byte
|
||||
0x95, 0x05, // Report Count (5),
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x05, 0x08, // Usage Page (LEDs),
|
||||
0x19, 0x01, // Usage Minimum (1),
|
||||
0x29, 0x05, // Usage Maximum (5),
|
||||
0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x75, 0x03, // Report Size (3),
|
||||
0x91, 0x03, // Output (Constant), ;LED report padding
|
||||
0x95, 0x06, // Report Count (6),
|
||||
0x75, 0x08, // Report Size (8),
|
||||
0x15, 0x00, // Logical Minimum (0),
|
||||
0x25, 0x68, // Logical Maximum(104),
|
||||
0x05, 0x07, // Usage Page (Key Codes),
|
||||
0x19, 0x00, // Usage Minimum (0),
|
||||
0x29, 0x68, // Usage Maximum (104),
|
||||
0x81, 0x00, // Input (Data, Array),
|
||||
0xc0 // End Collection
|
||||
};
|
||||
|
||||
#define CONFIG1_DESC_SIZE (9+9+9+7)
|
||||
#define KEYBOARD_HID_DESC_OFFSET (9+9)
|
||||
static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
|
||||
9, // bLength;
|
||||
2, // bDescriptorType;
|
||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength
|
||||
MSB(CONFIG1_DESC_SIZE),
|
||||
1, // bNumInterfaces
|
||||
1, // bConfigurationValue
|
||||
0, // iConfiguration
|
||||
0xC0, // bmAttributes
|
||||
50, // bMaxPower
|
||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||
9, // bLength
|
||||
4, // bDescriptorType
|
||||
KEYBOARD_INTERFACE, // bInterfaceNumber
|
||||
0, // bAlternateSetting
|
||||
1, // bNumEndpoints
|
||||
0x03, // bInterfaceClass (0x03 = HID)
|
||||
0x01, // bInterfaceSubClass (0x01 = Boot)
|
||||
0x01, // bInterfaceProtocol (0x01 = Keyboard)
|
||||
0, // iInterface
|
||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1
|
||||
9, // bLength
|
||||
0x21, // bDescriptorType
|
||||
0x11, 0x01, // bcdHID
|
||||
0, // bCountryCode
|
||||
1, // bNumDescriptors
|
||||
0x22, // bDescriptorType
|
||||
sizeof(keyboard_hid_report_desc), // wDescriptorLength
|
||||
0,
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
7, // bLength
|
||||
5, // bDescriptorType
|
||||
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
|
||||
0x03, // bmAttributes (0x03=intr)
|
||||
KEYBOARD_SIZE, 0, // wMaxPacketSize
|
||||
1 // bInterval
|
||||
};
|
||||
|
||||
// If you're desperate for a little extra code memory, these strings
|
||||
// can be completely removed if iManufacturer, iProduct, iSerialNumber
|
||||
// in the device desciptor are changed to zeros.
|
||||
struct usb_string_descriptor_struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
int16_t wString[];
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string0 = {
|
||||
4,
|
||||
3,
|
||||
{0x0409}
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string1 = {
|
||||
sizeof(STR_MANUFACTURER),
|
||||
3,
|
||||
STR_MANUFACTURER
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string2 = {
|
||||
sizeof(STR_PRODUCT),
|
||||
3,
|
||||
STR_PRODUCT
|
||||
};
|
||||
|
||||
// This table defines which descriptor data is sent for each specific
|
||||
// request from the host (in wValue and wIndex).
|
||||
static struct descriptor_list_struct {
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
const uint8_t *addr;
|
||||
uint8_t length;
|
||||
} PROGMEM descriptor_list[] = {
|
||||
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
|
||||
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
|
||||
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
|
||||
{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
|
||||
{0x0300, 0x0000, (const uint8_t *)&string0, 4},
|
||||
{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
|
||||
{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
|
||||
};
|
||||
#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Variables - these are the only non-stack RAM usage
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// zero when we are not configured, non-zero when enumerated
|
||||
static volatile uint8_t usb_configuration=0;
|
||||
|
||||
// which modifier keys are currently pressed
|
||||
// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
|
||||
// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
|
||||
uint8_t keyboard_modifier_keys=0;
|
||||
|
||||
// which keys are currently pressed, up to 6 keys may be down at once
|
||||
uint8_t keyboard_keys[6]={0,0,0,0,0,0};
|
||||
|
||||
// protocol setting from the host. We use exactly the same report
|
||||
// either way, so this variable only stores the setting since we
|
||||
// are required to be able to report which setting is in use.
|
||||
static uint8_t keyboard_protocol=1;
|
||||
|
||||
// the idle configuration, how often we send the report to the
|
||||
// host (ms * 4) even when it hasn't changed
|
||||
static uint8_t keyboard_idle_config=125;
|
||||
|
||||
// count until idle timeout
|
||||
static uint8_t keyboard_idle_count=0;
|
||||
|
||||
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
|
||||
volatile uint8_t keyboard_leds=0;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Public Functions - these are the API intended for the user
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
// initialize USB
|
||||
void usb_init(void)
|
||||
{
|
||||
HW_CONFIG();
|
||||
USB_FREEZE(); // enable USB
|
||||
PLL_CONFIG(); // config PLL
|
||||
while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
|
||||
USB_CONFIG(); // start USB clock
|
||||
UDCON = 0; // enable attach resistor
|
||||
usb_configuration = 0;
|
||||
UDIEN = (1<<EORSTE)|(1<<SOFE);
|
||||
sei();
|
||||
}
|
||||
|
||||
// return 0 if the USB is not configured, or the configuration
|
||||
// number selected by the HOST
|
||||
uint8_t usb_configured(void)
|
||||
{
|
||||
return usb_configuration;
|
||||
}
|
||||
|
||||
|
||||
// perform a single keystroke
|
||||
int8_t usb_keyboard_press(uint8_t key, uint8_t modifier)
|
||||
{
|
||||
int8_t r;
|
||||
|
||||
keyboard_modifier_keys = modifier;
|
||||
keyboard_keys[0] = key;
|
||||
r = usb_keyboard_send();
|
||||
if (r) return r;
|
||||
keyboard_modifier_keys = 0;
|
||||
keyboard_keys[0] = 0;
|
||||
return usb_keyboard_send();
|
||||
}
|
||||
|
||||
// send the contents of keyboard_keys and keyboard_modifier_keys
|
||||
int8_t usb_keyboard_send(void)
|
||||
{
|
||||
uint8_t i, intr_state, timeout;
|
||||
|
||||
if (!usb_configuration) return -1;
|
||||
intr_state = SREG;
|
||||
cli();
|
||||
UENUM = KEYBOARD_ENDPOINT;
|
||||
timeout = UDFNUML + 50;
|
||||
while (1) {
|
||||
// are we ready to transmit?
|
||||
if (UEINTX & (1<<RWAL)) break;
|
||||
SREG = intr_state;
|
||||
// has the USB gone offline?
|
||||
if (!usb_configuration) return -1;
|
||||
// have we waited too long?
|
||||
if (UDFNUML == timeout) return -1;
|
||||
// get ready to try checking again
|
||||
intr_state = SREG;
|
||||
cli();
|
||||
UENUM = KEYBOARD_ENDPOINT;
|
||||
}
|
||||
UEDATX = keyboard_modifier_keys;
|
||||
UEDATX = 0;
|
||||
for (i=0; i<6; i++) {
|
||||
UEDATX = keyboard_keys[i];
|
||||
}
|
||||
UEINTX = 0x3A;
|
||||
keyboard_idle_count = 0;
|
||||
SREG = intr_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Private Functions - not intended for general user consumption....
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
// USB Device Interrupt - handle all device-level events
|
||||
// the transmit buffer flushing is triggered by the start of frame
|
||||
//
|
||||
ISR(USB_GEN_vect)
|
||||
{
|
||||
uint8_t intbits, t, i;
|
||||
static uint8_t div4=0;
|
||||
|
||||
intbits = UDINT;
|
||||
UDINT = 0;
|
||||
if (intbits & (1<<EORSTI)) {
|
||||
UENUM = 0;
|
||||
UECONX = 1;
|
||||
UECFG0X = EP_TYPE_CONTROL;
|
||||
UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
|
||||
UEIENX = (1<<RXSTPE);
|
||||
usb_configuration = 0;
|
||||
}
|
||||
if ((intbits & (1<<SOFI)) && usb_configuration) {
|
||||
if (keyboard_idle_config && (++div4 & 3) == 0) {
|
||||
UENUM = KEYBOARD_ENDPOINT;
|
||||
if (UEINTX & (1<<RWAL)) {
|
||||
keyboard_idle_count++;
|
||||
if (keyboard_idle_count == keyboard_idle_config) {
|
||||
keyboard_idle_count = 0;
|
||||
UEDATX = keyboard_modifier_keys;
|
||||
UEDATX = 0;
|
||||
for (i=0; i<6; i++) {
|
||||
UEDATX = keyboard_keys[i];
|
||||
}
|
||||
UEINTX = 0x3A;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Misc functions to wait for ready and send/receive packets
|
||||
static inline void usb_wait_in_ready(void)
|
||||
{
|
||||
while (!(UEINTX & (1<<TXINI))) ;
|
||||
}
|
||||
static inline void usb_send_in(void)
|
||||
{
|
||||
UEINTX = ~(1<<TXINI);
|
||||
}
|
||||
static inline void usb_wait_receive_out(void)
|
||||
{
|
||||
while (!(UEINTX & (1<<RXOUTI))) ;
|
||||
}
|
||||
static inline void usb_ack_out(void)
|
||||
{
|
||||
UEINTX = ~(1<<RXOUTI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// USB Endpoint Interrupt - endpoint 0 is handled here. The
|
||||
// other endpoints are manipulated by the user-callable
|
||||
// functions, and the start-of-frame interrupt.
|
||||
//
|
||||
ISR(USB_COM_vect)
|
||||
{
|
||||
uint8_t intbits;
|
||||
const uint8_t *list;
|
||||
const uint8_t *cfg;
|
||||
uint8_t i, n, len, en;
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
uint16_t desc_val;
|
||||
const uint8_t *desc_addr;
|
||||
uint8_t desc_length;
|
||||
|
||||
UENUM = 0;
|
||||
intbits = UEINTX;
|
||||
if (intbits & (1<<RXSTPI)) {
|
||||
bmRequestType = UEDATX;
|
||||
bRequest = UEDATX;
|
||||
wValue = UEDATX;
|
||||
wValue |= (UEDATX << 8);
|
||||
wIndex = UEDATX;
|
||||
wIndex |= (UEDATX << 8);
|
||||
wLength = UEDATX;
|
||||
wLength |= (UEDATX << 8);
|
||||
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
|
||||
if (bRequest == GET_DESCRIPTOR) {
|
||||
list = (const uint8_t *)descriptor_list;
|
||||
for (i=0; ; i++) {
|
||||
if (i >= NUM_DESC_LIST) {
|
||||
UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
|
||||
return;
|
||||
}
|
||||
desc_val = pgm_read_word(list);
|
||||
if (desc_val != wValue) {
|
||||
list += sizeof(struct descriptor_list_struct);
|
||||
continue;
|
||||
}
|
||||
list += 2;
|
||||
desc_val = pgm_read_word(list);
|
||||
if (desc_val != wIndex) {
|
||||
list += sizeof(struct descriptor_list_struct)-2;
|
||||
continue;
|
||||
}
|
||||
list += 2;
|
||||
desc_addr = (const uint8_t *)pgm_read_word(list);
|
||||
list += 2;
|
||||
desc_length = pgm_read_byte(list);
|
||||
break;
|
||||
}
|
||||
len = (wLength < 256) ? wLength : 255;
|
||||
if (len > desc_length) len = desc_length;
|
||||
do {
|
||||
// wait for host ready for IN packet
|
||||
do {
|
||||
i = UEINTX;
|
||||
} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
|
||||
if (i & (1<<RXOUTI)) return; // abort
|
||||
// send IN packet
|
||||
n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
|
||||
for (i = n; i; i--) {
|
||||
UEDATX = pgm_read_byte(desc_addr++);
|
||||
}
|
||||
len -= n;
|
||||
usb_send_in();
|
||||
} while (len || n == ENDPOINT0_SIZE);
|
||||
return;
|
||||
}
|
||||
if (bRequest == SET_ADDRESS) {
|
||||
usb_send_in();
|
||||
usb_wait_in_ready();
|
||||
UDADDR = wValue | (1<<ADDEN);
|
||||
return;
|
||||
}
|
||||
if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
|
||||
usb_configuration = wValue;
|
||||
usb_send_in();
|
||||
cfg = endpoint_config_table;
|
||||
for (i=1; i<5; i++) {
|
||||
UENUM = i;
|
||||
en = pgm_read_byte(cfg++);
|
||||
UECONX = en;
|
||||
if (en) {
|
||||
UECFG0X = pgm_read_byte(cfg++);
|
||||
UECFG1X = pgm_read_byte(cfg++);
|
||||
}
|
||||
}
|
||||
UERST = 0x1E;
|
||||
UERST = 0;
|
||||
return;
|
||||
}
|
||||
if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = usb_configuration;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
|
||||
if (bRequest == GET_STATUS) {
|
||||
usb_wait_in_ready();
|
||||
i = 0;
|
||||
#ifdef SUPPORT_ENDPOINT_HALT
|
||||
if (bmRequestType == 0x82) {
|
||||
UENUM = wIndex;
|
||||
if (UECONX & (1<<STALLRQ)) i = 1;
|
||||
UENUM = 0;
|
||||
}
|
||||
#endif
|
||||
UEDATX = i;
|
||||
UEDATX = 0;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
#ifdef SUPPORT_ENDPOINT_HALT
|
||||
if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
|
||||
&& bmRequestType == 0x02 && wValue == 0) {
|
||||
i = wIndex & 0x7F;
|
||||
if (i >= 1 && i <= MAX_ENDPOINT) {
|
||||
usb_send_in();
|
||||
UENUM = i;
|
||||
if (bRequest == SET_FEATURE) {
|
||||
UECONX = (1<<STALLRQ)|(1<<EPEN);
|
||||
} else {
|
||||
UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
|
||||
UERST = (1 << i);
|
||||
UERST = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (wIndex == KEYBOARD_INTERFACE) {
|
||||
if (bmRequestType == 0xA1) {
|
||||
if (bRequest == HID_GET_REPORT) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = keyboard_modifier_keys;
|
||||
UEDATX = 0;
|
||||
for (i=0; i<6; i++) {
|
||||
UEDATX = keyboard_keys[i];
|
||||
}
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if (bRequest == HID_GET_IDLE) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = keyboard_idle_config;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if (bRequest == HID_GET_PROTOCOL) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = keyboard_protocol;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (bmRequestType == 0x21) {
|
||||
if (bRequest == HID_SET_REPORT) {
|
||||
usb_wait_receive_out();
|
||||
keyboard_leds = UEDATX;
|
||||
usb_ack_out();
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if (bRequest == HID_SET_IDLE) {
|
||||
keyboard_idle_config = (wValue >> 8);
|
||||
keyboard_idle_count = 0;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if (bRequest == HID_SET_PROTOCOL) {
|
||||
keyboard_protocol = wValue;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
#ifndef usb_serial_h__
|
||||
#define usb_serial_h__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void usb_init(void); // initialize everything
|
||||
uint8_t usb_configured(void); // is the USB port configured
|
||||
|
||||
int8_t usb_keyboard_press(uint8_t key, uint8_t modifier);
|
||||
int8_t usb_keyboard_send(void);
|
||||
extern uint8_t keyboard_modifier_keys;
|
||||
extern uint8_t keyboard_keys[6];
|
||||
extern volatile uint8_t keyboard_leds;
|
||||
|
||||
// This file does not include the HID debug functions, so these empty
|
||||
// macros replace them with nothing, so users can compile code that
|
||||
// has calls to these functions.
|
||||
#define usb_debug_putchar(c)
|
||||
#define usb_debug_flush_output()
|
||||
|
||||
|
||||
#define KEY_CTRL 0x01
|
||||
#define KEY_SHIFT 0x02
|
||||
#define KEY_ALT 0x04
|
||||
#define KEY_GUI 0x08
|
||||
#define KEY_LEFT_CTRL 0x01
|
||||
#define KEY_LEFT_SHIFT 0x02
|
||||
#define KEY_LEFT_ALT 0x04
|
||||
#define KEY_LEFT_GUI 0x08
|
||||
#define KEY_RIGHT_CTRL 0x10
|
||||
#define KEY_RIGHT_SHIFT 0x20
|
||||
#define KEY_RIGHT_ALT 0x40
|
||||
#define KEY_RIGHT_GUI 0x80
|
||||
|
||||
#define KEY_A 4
|
||||
#define KEY_B 5
|
||||
#define KEY_C 6
|
||||
#define KEY_D 7
|
||||
#define KEY_E 8
|
||||
#define KEY_F 9
|
||||
#define KEY_G 10
|
||||
#define KEY_H 11
|
||||
#define KEY_I 12
|
||||
#define KEY_J 13
|
||||
#define KEY_K 14
|
||||
#define KEY_L 15
|
||||
#define KEY_M 16
|
||||
#define KEY_N 17
|
||||
#define KEY_O 18
|
||||
#define KEY_P 19
|
||||
#define KEY_Q 20
|
||||
#define KEY_R 21
|
||||
#define KEY_S 22
|
||||
#define KEY_T 23
|
||||
#define KEY_U 24
|
||||
#define KEY_V 25
|
||||
#define KEY_W 26
|
||||
#define KEY_X 27
|
||||
#define KEY_Y 28
|
||||
#define KEY_Z 29
|
||||
#define KEY_1 30
|
||||
#define KEY_2 31
|
||||
#define KEY_3 32
|
||||
#define KEY_4 33
|
||||
#define KEY_5 34
|
||||
#define KEY_6 35
|
||||
#define KEY_7 36
|
||||
#define KEY_8 37
|
||||
#define KEY_9 38
|
||||
#define KEY_0 39
|
||||
#define KEY_ENTER 40
|
||||
#define KEY_ESC 41
|
||||
#define KEY_BACKSPACE 42
|
||||
#define KEY_TAB 43
|
||||
#define KEY_SPACE 44
|
||||
#define KEY_MINUS 45
|
||||
#define KEY_EQUAL 46
|
||||
#define KEY_LEFT_BRACE 47
|
||||
#define KEY_RIGHT_BRACE 48
|
||||
#define KEY_BACKSLASH 49
|
||||
#define KEY_NUMBER 50
|
||||
#define KEY_SEMICOLON 51
|
||||
#define KEY_QUOTE 52
|
||||
#define KEY_TILDE 53
|
||||
#define KEY_COMMA 54
|
||||
#define KEY_PERIOD 55
|
||||
#define KEY_SLASH 56
|
||||
#define KEY_CAPS_LOCK 57
|
||||
#define KEY_F1 58
|
||||
#define KEY_F2 59
|
||||
#define KEY_F3 60
|
||||
#define KEY_F4 61
|
||||
#define KEY_F5 62
|
||||
#define KEY_F6 63
|
||||
#define KEY_F7 64
|
||||
#define KEY_F8 65
|
||||
#define KEY_F9 66
|
||||
#define KEY_F10 67
|
||||
#define KEY_F11 68
|
||||
#define KEY_F12 69
|
||||
#define KEY_PRINTSCREEN 70
|
||||
#define KEY_SCROLL_LOCK 71
|
||||
#define KEY_PAUSE 72
|
||||
#define KEY_INSERT 73
|
||||
#define KEY_HOME 74
|
||||
#define KEY_PAGE_UP 75
|
||||
#define KEY_DELETE 76
|
||||
#define KEY_END 77
|
||||
#define KEY_PAGE_DOWN 78
|
||||
#define KEY_RIGHT 79
|
||||
#define KEY_LEFT 80
|
||||
#define KEY_DOWN 81
|
||||
#define KEY_UP 82
|
||||
#define KEY_NUM_LOCK 83
|
||||
#define KEYPAD_SLASH 84
|
||||
#define KEYPAD_ASTERIX 85
|
||||
#define KEYPAD_MINUS 86
|
||||
#define KEYPAD_PLUS 87
|
||||
#define KEYPAD_ENTER 88
|
||||
#define KEYPAD_1 89
|
||||
#define KEYPAD_2 90
|
||||
#define KEYPAD_3 91
|
||||
#define KEYPAD_4 92
|
||||
#define KEYPAD_5 93
|
||||
#define KEYPAD_6 94
|
||||
#define KEYPAD_7 95
|
||||
#define KEYPAD_8 96
|
||||
#define KEYPAD_9 97
|
||||
#define KEYPAD_0 98
|
||||
#define KEYPAD_PERIOD 99
|
||||
|
||||
|
||||
|
||||
|
||||
// Everything below this point is only intended for usb_serial.c
|
||||
#ifdef USB_SERIAL_PRIVATE_INCLUDE
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define EP_TYPE_CONTROL 0x00
|
||||
#define EP_TYPE_BULK_IN 0x81
|
||||
#define EP_TYPE_BULK_OUT 0x80
|
||||
#define EP_TYPE_INTERRUPT_IN 0xC1
|
||||
#define EP_TYPE_INTERRUPT_OUT 0xC0
|
||||
#define EP_TYPE_ISOCHRONOUS_IN 0x41
|
||||
#define EP_TYPE_ISOCHRONOUS_OUT 0x40
|
||||
|
||||
#define EP_SINGLE_BUFFER 0x02
|
||||
#define EP_DOUBLE_BUFFER 0x06
|
||||
|
||||
#define EP_SIZE(s) ((s) == 64 ? 0x30 : \
|
||||
((s) == 32 ? 0x20 : \
|
||||
((s) == 16 ? 0x10 : \
|
||||
0x00)))
|
||||
|
||||
#define MAX_ENDPOINT 4
|
||||
|
||||
#define LSB(n) (n & 255)
|
||||
#define MSB(n) ((n >> 8) & 255)
|
||||
|
||||
#if defined(__AVR_AT90USB162__)
|
||||
#define HW_CONFIG()
|
||||
#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
|
||||
#define USB_CONFIG() (USBCON = (1<<USBE))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#define HW_CONFIG() (UHWCON = 0x01)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x12)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_AT90USB646__)
|
||||
#define HW_CONFIG() (UHWCON = 0x81)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x1A)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_AT90USB1286__)
|
||||
#define HW_CONFIG() (UHWCON = 0x81)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x16)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#endif
|
||||
|
||||
// standard control endpoint request types
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
#define SET_FEATURE 3
|
||||
#define SET_ADDRESS 5
|
||||
#define GET_DESCRIPTOR 6
|
||||
#define GET_CONFIGURATION 8
|
||||
#define SET_CONFIGURATION 9
|
||||
#define GET_INTERFACE 10
|
||||
#define SET_INTERFACE 11
|
||||
// HID (human interface device)
|
||||
#define HID_GET_REPORT 1
|
||||
#define HID_GET_IDLE 2
|
||||
#define HID_GET_PROTOCOL 3
|
||||
#define HID_SET_REPORT 9
|
||||
#define HID_SET_IDLE 10
|
||||
#define HID_SET_PROTOCOL 11
|
||||
// CDC (communication class device)
|
||||
#define CDC_SET_LINE_CODING 0x20
|
||||
#define CDC_GET_LINE_CODING 0x21
|
||||
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
# src/lib-other
|
||||
Files taken from other projects
|
||||
|
||||
## links to original files
|
||||
|
||||
* [pjrc] (http://pjrc.com/teensy/)
|
||||
* [blinky] (http://pjrc.com/teensy/blinky.zip)
|
||||
* [usb_keyboard] (http://pjrc.com/teensy/usb_keyboard.zip)
|
||||
|
||||
* [peter-fleury] (http://homepage.hispeed.ch/peterfleury/)
|
||||
* note: This code is licensed under the GNU GPL
|
||||
(per [the author's web site]
|
||||
(http://homepage.hispeed.ch/peterfleury/avr-software.html)).
|
||||
The MIT License is compatible with GPL
|
||||
(see [the Wikipedia entry]
|
||||
(http://en.wikipedia.org/wiki/MIT_License),
|
||||
and [the list of compatible licenses]
|
||||
(http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses)
|
||||
on <http://www.gnu.org/>).
|
||||
* [i2cmaster] (http://homepage.hispeed.ch/peterfleury/i2cmaster.zip)
|
||||
|
||||
* [arduino] (https://github.com/arduino)
|
||||
* [arduino] (https://github.com/arduino/Arduino)
|
||||
* .../twi.c and .../twi.h
|
||||
* note: The version here is from the Ubuntu package, so it's probably
|
||||
old. The (new) version from github has dependencies galore on random
|
||||
other Arduino files, so it wasn't really usable.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (MIT) (see "license.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Common data types
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef DATA_TYPES_h
|
||||
#define DATA_TYPES_h
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
#define bool _Bool
|
||||
|
||||
#define true ((bool)1)
|
||||
#define false ((bool)0)
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* USB Keyboard Key Codes (usage page 0x07)
|
||||
*
|
||||
* Taken from [the HID Usage Tables pdf][1], Section 10,
|
||||
* which can be found on [the HID Page][2] at <http://www.usb.org>
|
||||
*
|
||||
* - `Boot Keyboard Req.` indicates that the usage code is one that should be
|
||||
* supported by the listed types of keyboards (104-key, ...) on boot
|
||||
*
|
||||
* - `KEY_` indicates a Keyboard key
|
||||
* - `KEYPAD_` indicates a Keypad key
|
||||
* - Multiple names concatenated in CamelCase indicate a single value
|
||||
* - Multiple names separated by `_`s indicate shifted or alternate values
|
||||
*
|
||||
* [1]: http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf
|
||||
* [2]: http://www.usb.org/developers/hidpage
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// Name ID // PC Mac Unix Boot Keyboard Req.
|
||||
// --------------------------- ---- -- --- ---- ---------------------
|
||||
|
||||
// (Reserved) 0x00 // √ √ √ 84/101/104
|
||||
|
||||
#define KEY_ErrorRollOver 0x01 // √ √ √ 84/101/104
|
||||
#define KEY_POSTFail 0x02 // √ √ √ 84/101/104
|
||||
#define KEY_ErrorUndefined 0x03 // √ √ √ 84/101/104
|
||||
#define KEY_a_A 0x04 // √ √ √ 84/101/104
|
||||
#define KEY_b_B 0x05 // √ √ √ 84/101/104
|
||||
#define KEY_c_C 0x06 // √ √ √ 84/101/104
|
||||
#define KEY_d_D 0x07 // √ √ √ 84/101/104
|
||||
#define KEY_e_E 0x08 // √ √ √ 84/101/104
|
||||
#define KEY_f_F 0x09 // √ √ √ 84/101/104
|
||||
#define KEY_g_G 0x0A // √ √ √ 84/101/104
|
||||
#define KEY_h_H 0x0B // √ √ √ 84/101/104
|
||||
#define KEY_i_I 0x0C // √ √ √ 84/101/104
|
||||
#define KEY_j_J 0x0D // √ √ √ 84/101/104
|
||||
#define KEY_k_K 0x0E // √ √ √ 84/101/104
|
||||
#define KEY_l_L 0x0F // √ √ √ 84/101/104
|
||||
#define KEY_m_M 0x10 // √ √ √ 84/101/104
|
||||
#define KEY_n_N 0x11 // √ √ √ 84/101/104
|
||||
#define KEY_o_O 0x12 // √ √ √ 84/101/104
|
||||
#define KEY_p_P 0x13 // √ √ √ 84/101/104
|
||||
#define KEY_q_Q 0x14 // √ √ √ 84/101/104
|
||||
#define KEY_r_R 0x15 // √ √ √ 84/101/104
|
||||
#define KEY_s_S 0x16 // √ √ √ 84/101/104
|
||||
#define KEY_t_T 0x17 // √ √ √ 84/101/104
|
||||
#define KEY_u_U 0x18 // √ √ √ 84/101/104
|
||||
#define KEY_v_V 0x19 // √ √ √ 84/101/104
|
||||
#define KEY_w_W 0x1A // √ √ √ 84/101/104
|
||||
#define KEY_x_X 0x1B // √ √ √ 84/101/104
|
||||
#define KEY_y_Y 0x1C // √ √ √ 84/101/104
|
||||
#define KEY_z_Z 0x1D // √ √ √ 84/101/104
|
||||
#define KEY_1_Exclamation 0x1E // √ √ √ 84/101/104
|
||||
#define KEY_2_At 0x1F // √ √ √ 84/101/104
|
||||
#define KEY_3_Pound 0x20 // √ √ √ 84/101/104
|
||||
#define KEY_4_Dollar 0x21 // √ √ √ 84/101/104
|
||||
#define KEY_5_Percent 0x22 // √ √ √ 84/101/104
|
||||
#define KEY_6_Caret 0x23 // √ √ √ 84/101/104
|
||||
#define KEY_7_Ampersand 0x24 // √ √ √ 84/101/104
|
||||
#define KEY_8_Asterisk 0x25 // √ √ √ 84/101/104
|
||||
#define KEY_9_LeftParenthesis 0x26 // √ √ √ 84/101/104
|
||||
#define KEY_0_RightParenthesis 0x27 // √ √ √ 84/101/104
|
||||
#define KEY_ReturnEnter 0x28 // √ √ √ 84/101/104
|
||||
#define KEY_Escape 0x29 // √ √ √ 84/101/104
|
||||
#define KEY_DeleteBackspace 0x2A // √ √ √ 84/101/104
|
||||
#define KEY_Tab 0x2B // √ √ √ 84/101/104
|
||||
#define KEY_Spacebar 0x2C // √ √ √ 84/101/104
|
||||
#define KEY_Dash_Underscore 0x2D // √ √ √ 84/101/104
|
||||
#define KEY_Equal_Plus 0x2E // √ √ √ 84/101/104
|
||||
#define KEY_LeftBracket_LeftBrace 0x2F // √ √ √ 84/101/104
|
||||
#define KEY_RightBracket_RightBrace 0x30 // √ √ √ 84/101/104
|
||||
#define KEY_Backslash_Pipe 0x31 // √ √ √ 84/101/104
|
||||
#define KEY_NonUS_Pound_Tilde 0x32 // √ √ √ 84/101/104
|
||||
#define KEY_Semicolon_Colon 0x33 // √ √ √ 84/101/104
|
||||
#define KEY_SingleQuote_DoubleQuote 0x34 // √ √ √ 84/101/104
|
||||
#define KEY_GraveAccent_Tilde 0x35 // √ √ √ 84/101/104
|
||||
#define KEY_Comma_LessThan 0x36 // √ √ √ 84/101/104
|
||||
#define KEY_Period_GreaterThan 0x37 // √ √ √ 84/101/104
|
||||
#define KEY_Slash_Question 0x38 // √ √ √ 84/101/104
|
||||
#define KEY_CapsLock 0x39 // √ √ √ 84/101/104
|
||||
#define KEY_F1 0x3A // √ √ √ 84/101/104
|
||||
#define KEY_F2 0x3B // √ √ √ 84/101/104
|
||||
#define KEY_F3 0x3C // √ √ √ 84/101/104
|
||||
#define KEY_F4 0x3D // √ √ √ 84/101/104
|
||||
#define KEY_F5 0x3E // √ √ √ 84/101/104
|
||||
#define KEY_F6 0x3F // √ √ √ 84/101/104
|
||||
#define KEY_F7 0x40 // √ √ √ 84/101/104
|
||||
#define KEY_F8 0x41 // √ √ √ 84/101/104
|
||||
#define KEY_F9 0x42 // √ √ √ 84/101/104
|
||||
#define KEY_F10 0x43 // √ √ √ 84/101/104
|
||||
#define KEY_F11 0x44 // √ √ √ 101/104
|
||||
#define KEY_F12 0x45 // √ √ √ 101/104
|
||||
#define KEY_PrintScreen 0x46 // √ √ √ 101/104
|
||||
#define KEY_ScrollLock 0x47 // √ √ √ 84/101/104
|
||||
#define KEY_Pause 0x48 // √ √ √ 101/104
|
||||
#define KEY_Insert 0x49 // √ √ √ 101/104
|
||||
#define KEY_Home 0x4A // √ √ √ 101/104
|
||||
#define KEY_PageUp 0x4B // √ √ √ 101/104
|
||||
#define KEY_DeleteForward 0x4C // √ √ √ 101/104
|
||||
#define KEY_End 0x4D // √ √ √ 101/104
|
||||
#define KEY_PageDown 0x4E // √ √ √ 101/104
|
||||
#define KEY_RightArrow 0x4F // √ √ √ 101/104
|
||||
#define KEY_LeftArrow 0x50 // √ √ √ 101/104
|
||||
#define KEY_DownArrow 0x51 // √ √ √ 101/104
|
||||
#define KEY_UpArrow 0x52 // √ √ √ 101/104
|
||||
|
||||
#define KEYPAD_NumLock_Clear 0x53 // √ √ √ 101/104
|
||||
#define KEYPAD_Slash 0x54 // √ √ √ 101/104
|
||||
#define KEYPAD_Asterisk 0x55 // √ √ √ 84/101/104
|
||||
#define KEYPAD_Minus 0x56 // √ √ √ 84/101/104
|
||||
#define KEYPAD_Plus 0x57 // √ √ √ 84/101/104
|
||||
#define KEYPAD_ENTER 0x58 // √ √ √ 101/104
|
||||
#define KEYPAD_1_End 0x59 // √ √ √ 84/101/104
|
||||
#define KEYPAD_2_DownArrow 0x5A // √ √ √ 84/101/104
|
||||
#define KEYPAD_3_PageDown 0x5B // √ √ √ 84/101/104
|
||||
#define KEYPAD_4_LeftArrow 0x5C // √ √ √ 84/101/104
|
||||
#define KEYPAD_5 0x5D // √ √ √ 84/101/104
|
||||
#define KEYPAD_6_RightArrow 0x5E // √ √ √ 84/101/104
|
||||
#define KEYPAD_7_Home 0x5F // √ √ √ 84/101/104
|
||||
#define KEYPAD_8_UpArrow 0x60 // √ √ √ 84/101/104
|
||||
#define KEYPAD_9_PageUp 0x61 // √ √ √ 84/101/104
|
||||
#define KEYPAD_0_Insert 0x62 // √ √ √ 84/101/104
|
||||
#define KEYPAD_Period_Delete 0x63 // √ √ √ 84/101/104
|
||||
|
||||
#define KEY_NonUS_Backslash_Pipe 0x64 // √ √ √ 84/101/104
|
||||
#define KEY_Application 0x65 // √ - √ 104
|
||||
#define KEY_Power 0x66 // - √ √ -
|
||||
|
||||
#define KEYPAD_Equal 0x67 // - √ - -
|
||||
|
||||
#define KEY_F13 0x68 // - √ - -
|
||||
#define KEY_F14 0x69 // - √ - -
|
||||
#define KEY_F15 0x6A // - √ - -
|
||||
#define KEY_F16 0x6B // - - - -
|
||||
#define KEY_F17 0x6C // - - - -
|
||||
#define KEY_F18 0x6D // - - - -
|
||||
#define KEY_F19 0x6E // - - - -
|
||||
#define KEY_F20 0x6F // - - - -
|
||||
#define KEY_F21 0x70 // - - - -
|
||||
#define KEY_F22 0x71 // - - - -
|
||||
#define KEY_F23 0x72 // - - - -
|
||||
#define KEY_F24 0x73 // - - - -
|
||||
#define KEY_Execute 0x74 // - - √ -
|
||||
#define KEY_Help 0x75 // - - √ -
|
||||
#define KEY_Menu 0x76 // - - √ -
|
||||
#define KEY_Select 0x77 // - - √ -
|
||||
#define KEY_Stop 0x78 // - - √ -
|
||||
#define KEY_Again 0x79 // - - √ -
|
||||
#define KEY_Undo 0x7A // - - √ -
|
||||
#define KEY_Cut 0x7B // - - √ -
|
||||
#define KEY_Copy 0x7C // - - √ -
|
||||
#define KEY_Paste 0x7D // - - √ -
|
||||
#define KEY_Find 0x7E // - - √ -
|
||||
#define KEY_Mute 0x7F // - - √ -
|
||||
#define KEY_VolumeUp 0x80 // - - √ -
|
||||
#define KEY_VolumeDown 0x81 // - - √ -
|
||||
#define KEY_LockingCapsLock 0x82 // - - √ -
|
||||
#define KEY_LockingNumLock 0x83 // - - √ -
|
||||
#define KEY_LockingScrollLock 0x84 // - - √ -
|
||||
|
||||
#define KEYPAD_Comma 0x85 // - - - -
|
||||
#define KEYPAD_Equal 0x86 // - - - -
|
||||
|
||||
#define KEY_International1 0x87 // - - - -
|
||||
#define KEY_International2 0x88 // - - - -
|
||||
#define KEY_International3 0x89 // - - - -
|
||||
#define KEY_International4 0x8A // - - - -
|
||||
#define KEY_International5 0x8B // - - - -
|
||||
#define KEY_International6 0x8C // - - - -
|
||||
#define KEY_International7 0x8D // - - - -
|
||||
#define KEY_International8 0x8E // - - - -
|
||||
#define KEY_International9 0x8F // - - - -
|
||||
#define KEY_LANG1 0x90 // - - - -
|
||||
#define KEY_LANG2 0x91 // - - - -
|
||||
#define KEY_LANG3 0x92 // - - - -
|
||||
#define KEY_LANG4 0x93 // - - - -
|
||||
#define KEY_LANG5 0x94 // - - - -
|
||||
#define KEY_LANG6 0x95 // - - - -
|
||||
#define KEY_LANG7 0x96 // - - - -
|
||||
#define KEY_LANG8 0x97 // - - - -
|
||||
#define KEY_LANG9 0x98 // - - - -
|
||||
#define KEY_AlternateErase 0x99 // - - - -
|
||||
#define KEY_SysReq_Attention 0x9A // - - - -
|
||||
#define KEY_Cancel 0x9B // - - - -
|
||||
#define KEY_Clear 0x9C // - - - -
|
||||
#define KEY_Prior 0x9D // - - - -
|
||||
#define KEY_Return 0x9E // - - - -
|
||||
#define KEY_Separator 0x9F // - - - -
|
||||
#define KEY_Out 0xA0 // - - - -
|
||||
#define KEY_Oper 0xA1 // - - - -
|
||||
#define KEY_Clear_Again 0xA2 // - - - -
|
||||
#define KEY_CrSel_Props 0xA3 // - - - -
|
||||
#define KEY_ExSel 0xA4 // - - - -
|
||||
|
||||
// (Reserved) 0xA5..0xAF // - - - -
|
||||
|
||||
#define KEYPAD_00 0xB0 // - - - -
|
||||
#define KEYPAD_000 0xB1 // - - - -
|
||||
|
||||
#define KEY_ThousandsSeparator 0xB2 // - - - -
|
||||
#define KEY_DecimalSeparator 0xB3 // - - - -
|
||||
#define KEY_CurrencyUnit 0xB4 // - - - -
|
||||
#define KEY_CurrencySubunit 0xB5 // - - - -
|
||||
|
||||
#define KEYPAD_LeftParenthesis 0xB6 // - - - -
|
||||
#define KEYPAD_RightParenthesis 0xB7 // - - - -
|
||||
#define KEYPAD_LeftBrace 0xB8 // - - - -
|
||||
#define KEYPAD_RightBrace 0xB9 // - - - -
|
||||
|
||||
#define KEYPAD_Tab 0xBA // - - - -
|
||||
#define KEYPAD_Backspace 0xBB // - - - -
|
||||
#define KEYPAD_A 0xBC // - - - -
|
||||
#define KEYPAD_B 0xBD // - - - -
|
||||
#define KEYPAD_C 0xBE // - - - -
|
||||
#define KEYPAD_D 0xBF // - - - -
|
||||
#define KEYPAD_E 0xC0 // - - - -
|
||||
#define KEYPAD_F 0xC1 // - - - -
|
||||
#define KEYPAD_XOR 0xC2 // - - - -
|
||||
#define KEYPAD_Caret 0xC3 // - - - -
|
||||
#define KEYPAD_Percent 0xC4 // - - - -
|
||||
#define KEYPAD_LessThan 0xC5 // - - - -
|
||||
#define KEYPAD_GreaterThan 0xC6 // - - - -
|
||||
#define KEYPAD_Ampersand 0xC7 // - - - -
|
||||
#define KEYPAD_AmpersandAmpersand 0xC8 // - - - -
|
||||
#define KEYPAD_Pipe 0xC9 // - - - -
|
||||
#define KEYPAD_PipePipe 0xCA // - - - -
|
||||
#define KEYPAD_Colon 0xCB // - - - -
|
||||
#define KEYPAD_Pound 0xCC // - - - -
|
||||
#define KEYPAD_Space 0xCD // - - - -
|
||||
#define KEYPAD_At 0xCE // - - - -
|
||||
#define KEYPAD_Exclamation 0xCF // - - - -
|
||||
#define KEYPAD_MemoryStore 0xD0 // - - - -
|
||||
#define KEYPAD_MemoryRecall 0xD1 // - - - -
|
||||
#define KEYPAD_MemoryClear 0xD2 // - - - -
|
||||
#define KEYPAD_MemoryAdd 0xD3 // - - - -
|
||||
#define KEYPAD_MemorySubtract 0xD4 // - - - -
|
||||
#define KEYPAD_MemoryMultiply 0xD5 // - - - -
|
||||
#define KEYPAD_MemoryDivide 0xD6 // - - - -
|
||||
#define KEYPAD_PlusMinux 0xD7 // - - - -
|
||||
#define KEYPAD_Clear 0xD8 // - - - -
|
||||
#define KEYPAD_ClearEntry 0xD9 // - - - -
|
||||
#define KEYPAD_Binary 0xDA // - - - -
|
||||
#define KEYPAD_Octal 0xDB // - - - -
|
||||
#define KEYPAD_Decimal 0xDC // - - - -
|
||||
#define KEYPAD_Hexadecimal 0xDD // - - - -
|
||||
|
||||
// (Reserved) 0xDE..0xDF // - - - -
|
||||
|
||||
#define KEY_LeftControl 0xE0 // √ √ √ 84/101/104
|
||||
#define KEY_LeftShift 0xE1 // √ √ √ 84/101/104
|
||||
#define KEY_LeftAlt 0xE2 // √ √ √ 84/101/104
|
||||
#define KEY_LeftGUI 0xE3 // √ √ √ 104
|
||||
#define KEY_RightControl 0xE4 // √ √ √ 101/104
|
||||
#define KEY_RightShift 0xE5 // √ √ √ 84/101/104
|
||||
#define KEY_RightAlt 0xE6 // √ √ √ 101/104
|
||||
#define KEY_RightGUI 0xE7 // √ √ √ 104
|
||||
|
||||
// (Reserved) 0xE8..0xFFFF // - - - -
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* USB LED Codes (usage page 0x08)
|
||||
*
|
||||
* Taken from [the HID Usage Tables pdf][1], Section 11,
|
||||
* which can be found on [the HID Page][2] at <http://www.usb.org>
|
||||
*
|
||||
* - applicable Usage Types (from Section 3.4)
|
||||
* - OOC : On/Off Control
|
||||
* - Sel : Selector
|
||||
* - DV : Dynamic Value
|
||||
* - US : Usage Switch
|
||||
* - UM : Usage Modifier
|
||||
*
|
||||
* [1]: http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf
|
||||
* [2]: http://www.usb.org/developers/hidpage
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// Name ID Usage Type Section of HID Tables
|
||||
// --------------------------- ---- ---------- ----------------------
|
||||
|
||||
// (Undefined) 0x00 // - -
|
||||
|
||||
#define LED_NumLock 0x01 // OOC 11.1
|
||||
#define LED_CapsLock 0x02 // OOC 11.1
|
||||
#define LED_ScrollLock 0x03 // OOC 11.1
|
||||
#define LED_Compose 0x04 // OOC 11.1
|
||||
#define LED_Kana 0x05 // OOC 11.1
|
||||
#define LED_Power 0x06 // OOC 11.6
|
||||
#define LED_Shift 0x07 // OOC 11.1
|
||||
#define LED_DoNotDisturb 0x08 // OOC 11.2
|
||||
#define LED_Mute 0x09 // OOC 11.3
|
||||
#define LED_ToneEnable 0x0A // OOC 11.3
|
||||
#define LED_HighCutFilter 0x0B // OOC 11.3
|
||||
#define LED_LowCutFilter 0x0C // OOC 11.3
|
||||
#define LED_EqualizerEnable 0x0D // OOC 11.3
|
||||
#define LED_SoundFieldOn 0x0E // OOC 11.3
|
||||
#define LED_SurroundOn 0x0F // OOC 11.3
|
||||
#define LED_Repeat 0x10 // OOC 11.3
|
||||
#define LED_Stereo 0x11 // OOC 11.3
|
||||
#define LED_SamplingRateDetect 0x12 // OOC 11.3
|
||||
#define LED_Spinning 0x13 // OOC 11.4
|
||||
#define LED_CAV 0x14 // OOC 11.3
|
||||
#define LED_CLV 0x15 // OOC 11.3
|
||||
#define LED_RecordingFormatDetect 0x16 // OOC 11.4
|
||||
#define LED_OffHook 0x17 // OOC 11.2
|
||||
#define LED_Ring 0x18 // OOC 11.2
|
||||
#define LED_MessageWaiting 0x19 // OOC 11.2
|
||||
#define LED_DataMode 0x1A // OOC 11.2
|
||||
#define LED_BatteryOperation 0x1B // OOC 11.6
|
||||
#define LED_BatteryOK 0x1C // OOC 11.6
|
||||
#define LED_BatteryLow 0x1D // OOC 11.6
|
||||
#define LED_Speaker 0x1E // OOC 11.2
|
||||
#define LED_HeadSet 0x1F // OOC 11.2
|
||||
#define LED_Hold 0x20 // OOC 11.2
|
||||
#define LED_Microphone 0x21 // OOC 11.2
|
||||
#define LED_Coverage 0x22 // OOC 11.2
|
||||
#define LED_NightMode 0x23 // OOC 11.2
|
||||
#define LED_SendCalls 0x24 // OOC 11.2
|
||||
#define LED_CallPickup 0x25 // OOC 11.2
|
||||
#define LED_Conference 0x26 // OOC 11.2
|
||||
#define LED_Standby 0x27 // OOC 11.6
|
||||
#define LED_CameraOn 0x28 // OOC 11.3
|
||||
#define LED_CameraOff 0x29 // OOC 11.3
|
||||
#define LED_OnLine 0x2A // OOC 11.6
|
||||
#define LED_OffLine 0x2B // OOC 11.6
|
||||
#define LED_Busy 0x2C // OOC 11.6
|
||||
#define LED_Ready 0x2D // OOC 11.6
|
||||
#define LED_PaperOut 0x2E // OOC 11.5
|
||||
#define LED_PaperJam 0x2F // OOC 11.5
|
||||
#define LED_Remote 0x30 // OOC 11.6
|
||||
#define LED_Forward 0x31 // OOC 11.4
|
||||
#define LED_Reverse 0x32 // OOC 11.4
|
||||
#define LED_Stop 0x33 // OOC 11.4
|
||||
#define LED_Rewind 0x34 // OOC 11.4
|
||||
#define LED_FastForward 0x35 // OOC 11.4
|
||||
#define LED_Play 0x36 // OOC 11.4
|
||||
#define LED_Pause 0x37 // OOC 11.4
|
||||
#define LED_Record 0x38 // OOC 11.4
|
||||
#define LED_Error 0x39 // OOC 11.6
|
||||
#define LED_UsageSelectedIndicator 0x3A // US 11.6
|
||||
#define LED_UsageInUseIndicator 0x3B // US 11.6
|
||||
#define LED_UsageMultiModeIndicator 0x3C // UM 11.6
|
||||
#define LED_IndicatorOn 0x3D // Sel 11.6
|
||||
#define LED_IndicatorFlash 0x3E // Sel 11.6
|
||||
#define LED_IndicatorSlowBlink 0x3F // Sel 11.6
|
||||
#define LED_IndicatorFastBlink 0x40 // Sel 11.6
|
||||
#define LED_IndicatorOff 0x41 // Sel 11.6
|
||||
#define LED_FlashOnTime 0x42 // DV 11.6
|
||||
#define LED_SlowBlinkOnTime 0x43 // DV 11.6
|
||||
#define LED_SlowBlinkOffTime 0x44 // DV 11.6
|
||||
#define LED_FastBlinkOnTime 0x45 // DV 11.6
|
||||
#define LED_FastBlinkOffTime 0x46 // DV 11.6
|
||||
#define LED_UsageIndicatorColor 0x47 // UM 11.6
|
||||
#define LED_IndicatorRed 0x48 // Sel 11.6
|
||||
#define LED_IndicatorGreen 0x49 // Sel 11.6
|
||||
#define LED_IndicatorAmber 0x4A // Sel 11.6
|
||||
#define LED_GenericIndicator 0x4B // OOC 11.6
|
||||
#define LED_SystemSuspend 0x4C // OOC 11.6
|
||||
#define LED_ExternalPowerConnected 0x4D // OOC 11.6
|
||||
|
||||
// (Reserved) 0x4E..0xFFFF // - -
|
21
src/makefile
21
src/makefile
|
@ -2,16 +2,27 @@
|
|||
# This is mostly a stub at the moment, but I'm keeping it separate so I can
|
||||
# mess with it later without changing the original
|
||||
# -----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 Ben Blazak
|
||||
# Released under The MIT License (MIT) (see "license.md") at
|
||||
# <https://github.com/benblazak/ergodox-firmware>
|
||||
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
# Released under The MIT License (MIT) (see "license.md")
|
||||
# Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
SRC = $(shell find -name '*.c')
|
||||
TARGET = ergodox-firmware
|
||||
|
||||
SRC = $(shell find -maxdepth 1 -name '*.c') \
|
||||
$(shell find ./keyboard -name '*.c') \
|
||||
$(shell find ./lib -name '*.c') \
|
||||
./lib-other/peter-fleury/i2cmaster/twimaster.c \
|
||||
./lib-other/pjrc/blinky/print.c \
|
||||
./lib-other/pjrc/blinky/usb_debug_only.c \
|
||||
./lib-other/arduino/arduino/libraries/Wire/utility/twi.c
|
||||
|
||||
|
||||
EXTRAINCDIRS = .
|
||||
|
||||
TEENSY_MAKE = $(MAKE) -f 'lib/pjrc/Makefile' \
|
||||
TEENSY_MAKE = $(MAKE) -f 'lib-other/pjrc/blinky/Makefile' \
|
||||
TARGET='$(TARGET)' \
|
||||
SRC='$(SRC)' \
|
||||
EXTRAINCDIRS='$(EXTRAINCDIRS)'
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
#include <stdio.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "lib-other/pjrc/blinky/print.h"
|
||||
#include "lib-other/pjrc/blinky/usb_debug_only.h"
|
||||
|
||||
#define TEENSY_2_0_h_INCLUDE_PRIVATE
|
||||
#include "keyboard/ergodox/teensy-2-0.h"
|
||||
|
||||
int test_i2c(void);
|
||||
int test_kb_teensy(void);
|
||||
int main(void);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int main(void) {
|
||||
test_i2c();
|
||||
print("--------------");
|
||||
test_kb_teensy();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int test_i2c(void) {
|
||||
usb_init();
|
||||
_delay_ms(500); // just to be safe
|
||||
|
||||
uint8_t ret;
|
||||
|
||||
uint8_t len;
|
||||
char str[10];
|
||||
|
||||
print("\nhello");
|
||||
|
||||
ret = teensy_init();
|
||||
print("\nteensy_init() returned: 0x"); phex(ret);
|
||||
|
||||
ret = mcp23018_init();
|
||||
print("\nmcp23018_init() returned: 0x"); phex(ret);
|
||||
|
||||
usb_debug_flush_output();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int test_kb_teensy(void) {
|
||||
}
|
||||
|
Loading…
Reference in New Issue