Rev 771 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 771 | Rev 902 | ||
---|---|---|---|
1 | /**************************************************************************** |
1 | /**************************************************************************** |
2 | * Copyright (C) 2009-2010 by Claas Anders "CaScAdE" Rathje * |
2 | * Copyright (C) 2009-2011 by Claas Anders "CaScAdE" Rathje * |
3 | * admiralcascade@gmail.com * |
3 | * admiralcascade@gmail.com * |
4 | * Project-URL: http://www.mylifesucks.de/oss/c-strom/ * |
4 | * Project-URL: http://www.mylifesucks.de/oss/c-strom/ * |
5 | * * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License. * |
8 | * the Free Software Foundation; either version 2 of the License. * |
9 | * * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
13 | * GNU General Public License for more details. * |
14 | * * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the * |
16 | * along with this program; if not, write to the * |
17 | * Free Software Foundation, Inc., * |
17 | * Free Software Foundation, Inc., * |
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
19 | ****************************************************************************/ |
19 | ****************************************************************************/ |
20 | 20 | ||
21 | 21 | ||
22 | /**************************************************************************** |
22 | /**************************************************************************** |
23 | * * |
23 | * * |
24 | * Most of the i²c/twi code is originally from * |
24 | * Most of the i²c/twi code is originally from * |
25 | * http://www.rn-wissen.de/index.php/TWI_Slave_mit_avr-gcc * |
25 | * http://www.rn-wissen.de/index.php/TWI_Slave_mit_avr-gcc * |
26 | * * |
26 | * * |
27 | ****************************************************************************/ |
27 | ****************************************************************************/ |
28 | 28 | ||
29 | #include <avr/interrupt.h> |
29 | #include <avr/interrupt.h> |
30 | #include <util/twi.h> |
30 | #include <util/twi.h> |
31 | #include "i2c_slave.h" |
31 | #include "i2c_slave.h" |
32 | #include "spi_union.h" |
32 | #include "spi_union.h" |
33 | 33 | ||
34 | void init_twi_slave(uint8_t address) { |
34 | void init_twi_slave(uint8_t address) { |
35 | TWAR = address; |
35 | TWAR = address; |
36 | TWCR &= ~(1 << TWSTA) | (1 << TWSTO); |
36 | TWCR &= ~(1 << TWSTA) | (1 << TWSTO); |
37 | TWCR |= (1 << TWEA) | (1 << TWEN) | (1 << TWIE); |
37 | TWCR |= (1 << TWEA) | (1 << TWEN) | (1 << TWIE); |
38 | i2c_buf_adr = 0xFF; |
38 | i2c_buf_adr = 0xFF; |
39 | //sei(); |
39 | //sei(); |
40 | } |
40 | } |
41 | 41 | ||
42 | ISR(TWI_vect) { |
42 | ISR(TWI_vect) { |
43 | uint8_t data = 0; |
43 | uint8_t data = 0; |
44 | //PORTD ^= (1 << PD7); // toggle LED for test |
44 | //PORTD ^= (1 << PD7); // toggle LED for test |
45 | switch (TW_STATUS) { |
45 | switch (TW_STATUS) { |
46 | case TW_SR_SLA_ACK: // 0x60 Slave Receiver, wurde adressiert |
46 | case TW_SR_SLA_ACK: // 0x60 Slave Receiver, wurde adressiert |
47 | TWCR_ACK; // next byte received |
47 | TWCR_ACK; // next byte received |
48 | i2c_buf_adr = 0xFF; // buf_adr undef |
48 | i2c_buf_adr = 0xFF; // buf_adr undef |
49 | break; |
49 | break; |
50 | case TW_SR_DATA_ACK: // 0x80 Slave Receiver,Daten empfangen |
50 | case TW_SR_DATA_ACK: // 0x80 Slave Receiver,Daten empfangen |
51 | data = TWDR; //Empfangene Daten auslesen |
51 | data = TWDR; //Empfangene Daten auslesen |
52 | if (i2c_buf_adr == 0xFF) {//erster Zugriff, Bufferposition setzen |
52 | if (i2c_buf_adr == 0xFF) {//erster Zugriff, Bufferposition setzen |
53 | if (data <= I2C_BUFFER_SIZE) { //Kontrolle ob gewünschte Adresse im erlaubten bereich |
53 | if (data <= I2C_BUFFER_SIZE) { //Kontrolle ob gewünschte Adresse im erlaubten bereich |
54 | i2c_buf_adr = data; //Bufferposition wie adressiert setzen |
54 | i2c_buf_adr = data; //Bufferposition wie adressiert setzen |
55 | } else { |
55 | } else { |
56 | i2c_buf_adr = 0; //Adresse auf Null setzen. Ist das sinnvoll? |
56 | i2c_buf_adr = 0; //Adresse auf Null setzen. Ist das sinnvoll? |
57 | } |
57 | } |
58 | TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern |
58 | TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern |
59 | } else {//weiterer Zugriff, Daten empfangen |
59 | } else {//weiterer Zugriff, Daten empfangen |
60 | i2c_rx_buffer[i2c_buf_adr] = data; //Daten in Buffer schreiben |
60 | i2c_rx_buffer[i2c_buf_adr] = data; //Daten in Buffer schreiben |
61 | i2c_buf_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff |
61 | i2c_buf_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff |
62 | if (i2c_buf_adr < (I2C_BUFFER_SIZE - 1)) {//im Buffer ist noch Platz für mehr als ein Byte |
62 | if (i2c_buf_adr < (I2C_BUFFER_SIZE - 1)) {//im Buffer ist noch Platz für mehr als ein Byte |
63 | TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern |
63 | TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern |
64 | } else {//es kann nur noch ein Byte kommen, dann ist der Buffer voll |
64 | } else {//es kann nur noch ein Byte kommen, dann ist der Buffer voll |
65 | TWCR_NACK; //letztes Byte lesen, dann NACK, um vollen Buffer zu signaliseren |
65 | TWCR_NACK; //letztes Byte lesen, dann NACK, um vollen Buffer zu signaliseren |
66 | } |
66 | } |
67 | } |
67 | } |
68 | break; |
68 | break; |
69 | case TW_ST_SLA_ACK: //?!? |
69 | case TW_ST_SLA_ACK: //?!? |
70 | case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, weitere Daten wurden angefordert |
70 | case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, weitere Daten wurden angefordert |
71 | if (i2c_buf_adr == 0xFF) {//zuvor keine Leseadresse angegeben! |
71 | if (i2c_buf_adr == 0xFF) {//zuvor keine Leseadresse angegeben! |
72 | i2c_buf_adr = 0; |
72 | i2c_buf_adr = 0; |
73 | } |
73 | } |
74 | TWDR = i2c_tx_buffer[i2c_buf_adr]; //Datenbyte senden |
74 | TWDR = i2c_tx_buffer[i2c_buf_adr]; //Datenbyte senden |
75 | i2c_buf_adr++; //bufferadresse für nächstes Byte weiterzählen |
75 | i2c_buf_adr++; //bufferadresse für nächstes Byte weiterzählen |
76 | if (i2c_buf_adr < (I2C_BUFFER_SIZE - 1)) {//im Buffer ist mehr als ein Byte, das gesendet werden kann |
76 | if (i2c_buf_adr < (I2C_BUFFER_SIZE - 1)) {//im Buffer ist mehr als ein Byte, das gesendet werden kann |
77 | TWCR_ACK; //nächstes Byte senden, danach ACK erwarten |
77 | TWCR_ACK; //nächstes Byte senden, danach ACK erwarten |
78 | } else { |
78 | } else { |
79 | TWCR_NACK; //letztes Byte senden, danach NACK erwarten |
79 | TWCR_NACK; //letztes Byte senden, danach NACK erwarten |
80 | } |
80 | } |
81 | break; |
81 | break; |
82 | case TW_ST_DATA_NACK: //0xC0 Keine Daten mehr gefordert |
82 | case TW_ST_DATA_NACK: //0xC0 Keine Daten mehr gefordert |
83 | case TW_SR_DATA_NACK: //0x88 |
83 | case TW_SR_DATA_NACK: //0x88 |
84 | case TW_ST_LAST_DATA: //0xC8 Last data byte in TWDR has been transmitted (TWEA = 0); ACK has been received |
84 | case TW_ST_LAST_DATA: //0xC8 Last data byte in TWDR has been transmitted (TWEA = 0); ACK has been received |
85 | case TW_SR_STOP: // 0xA0 STOP empfangen |
85 | case TW_SR_STOP: // 0xA0 STOP empfangen |
86 | default: |
86 | default: |
87 | TWCR_RESET; //Übertragung beenden, warten bis zur nächsten Adressierung |
87 | TWCR_RESET; //Übertragung beenden, warten bis zur nächsten Adressierung |
88 | break; |
88 | break; |
89 | } |
89 | } |
90 | } |
90 | } |
91 | 91 |