aboutsummaryrefslogtreecommitdiff
path: root/keyboards/tkc1800/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/tkc1800/i2c.c')
-rw-r--r--keyboards/tkc1800/i2c.c166
1 files changed, 0 insertions, 166 deletions
diff --git a/keyboards/tkc1800/i2c.c b/keyboards/tkc1800/i2c.c
deleted file mode 100644
index cd2b835d5..000000000
--- a/keyboards/tkc1800/i2c.c
+++ /dev/null
@@ -1,166 +0,0 @@
1#include <util/twi.h>
2#include <avr/io.h>
3#include <stdlib.h>
4#include <avr/interrupt.h>
5#include <util/twi.h>
6#include <stdbool.h>
7#include "i2c.h"
8
9#ifdef USE_I2C
10
11// Limits the amount of we wait for any one i2c transaction.
12// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is
13// 9 bits, a single transaction will take around 90μs to complete.
14//
15// (F_CPU/SCL_CLOCK) => # of μC cycles to transfer a bit
16// poll loop takes at least 8 clock cycles to execute
17#define I2C_LOOP_TIMEOUT (9+1)*(F_CPU/SCL_CLOCK)/8
18
19#define BUFFER_POS_INC() (slave_buffer_pos = (slave_buffer_pos+1)%SLAVE_BUFFER_SIZE)
20
21volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
22
23static volatile uint8_t slave_buffer_pos;
24static volatile bool slave_has_register_set = false;
25
26// Wait for an i2c operation to finish
27inline static
28void i2c_delay(void) {
29 uint16_t lim = 0;
30 while(!(TWCR & (1<<TWINT)) && lim < I2C_LOOP_TIMEOUT)
31 lim++;
32
33 // easier way, but will wait slightly longer
34 // _delay_us(100);
35}
36
37// Setup twi to run at 100kHz
38void i2c_master_init(void) {
39 // no prescaler
40 TWSR = 0;
41 // Set TWI clock frequency to SCL_CLOCK. Need TWBR>10.
42 // Check datasheets for more info.
43 TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
44}
45
46// Start a transaction with the given i2c slave address. The direction of the
47// transfer is set with I2C_READ and I2C_WRITE.
48// returns: 0 => success
49// 1 => error
50uint8_t i2c_master_start(uint8_t address) {
51 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
52
53 i2c_delay();
54
55 // check that we started successfully
56 if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START))
57 return 1;
58
59 // send device address
60 TWDR = address;
61 TWCR = (1<<TWINT) | (1<<TWEN);
62
63 i2c_delay();
64
65 if ( (TW_STATUS != TW_MT_SLA_ACK) && (TW_STATUS != TW_MR_SLA_ACK) )
66 return 1; // slave did not acknowledge
67 else
68 return 0; // success
69}
70
71
72// Finish the i2c transaction.
73void i2c_master_stop(void) {
74 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
75
76 uint16_t lim = 0;
77 while(!(TWCR & (1<<TWSTO)) && lim < I2C_LOOP_TIMEOUT)
78 lim++;
79}
80
81// Write one byte to the i2c slave.
82// returns 0 => slave ACK
83// 1 => slave NACK
84uint8_t i2c_master_write(uint8_t data) {
85 TWDR = data;
86 TWCR = (1<<TWINT) | (1<<TWEN);
87
88 i2c_delay();
89
90 // check if the slave acknowledged us
91 return (TW_STATUS == TW_MT_DATA_ACK) ? 0 : 1;
92}
93
94// Read one byte from the i2c slave. If ack=1 the slave is acknowledged,
95// if ack=0 the acknowledge bit is not set.
96// returns: byte read from i2c device
97uint8_t i2c_master_read(int ack) {
98 TWCR = (1<<TWINT) | (1<<TWEN) | (ack<<TWEA);
99
100 i2c_delay();
101 return TWDR;
102}
103
104void i2c_reset_state(void) {
105 TWCR = 0;
106}
107
108void i2c_slave_init(uint8_t address) {
109 TWAR = address << 0; // slave i2c address
110 // TWEN - twi enable
111 // TWEA - enable address acknowledgement
112 // TWINT - twi interrupt flag
113 // TWIE - enable the twi interrupt
114 TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
115}
116
117ISR(TWI_vect);
118
119ISR(TWI_vect) {
120 uint8_t ack = 1;
121 switch(TW_STATUS) {
122 case TW_SR_SLA_ACK:
123 // this device has been addressed as a slave receiver
124 slave_has_register_set = false;
125 break;
126
127 case TW_SR_DATA_ACK:
128 // this device has received data as a slave receiver
129 // The first byte that we receive in this transaction sets the location
130 // of the read/write location of the slaves memory that it exposes over
131 // i2c. After that, bytes will be written at slave_buffer_pos, incrementing
132 // slave_buffer_pos after each write.
133 if(!slave_has_register_set) {
134 slave_buffer_pos = TWDR;
135 // don't acknowledge the master if this memory loctaion is out of bounds
136 if ( slave_buffer_pos >= SLAVE_BUFFER_SIZE ) {
137 ack = 0;
138 slave_buffer_pos = 0;
139 }
140 slave_has_register_set = true;
141 } else {
142 i2c_slave_buffer[slave_buffer_pos] = TWDR;
143 BUFFER_POS_INC();
144 }
145 break;
146
147 case TW_ST_SLA_ACK:
148 case TW_ST_DATA_ACK:
149 // master has addressed this device as a slave transmitter and is
150 // requesting data.
151 TWDR = i2c_slave_buffer[slave_buffer_pos];
152 BUFFER_POS_INC();
153 break;
154
155 case TW_BUS_ERROR: // something went wrong, reset twi state
156 TWCR = 0;
157 default:
158 break;
159 }
160 // Reset everything, so we are ready for the next TWI interrupt
161 TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
162}
163
164
165
166#endif