3
* @brief TWI communication for Lego AVR
11
#include <embox/unit.h>
12
#include <kernel/panic.h>
14
#include <hal/system.h>
15
#include <drivers/at91sam7s256.h>
17
#include <drivers/twi.h>
19
EMBOX_UNIT_INIT(twi_init);
21
#define TWICLK 400000L //TODO move to global config -- special to system where runs
22
#define CLDIV (((SYS_CLOCK/TWICLK)/2)-3)
24
static uint32_t twi_pending;
25
static uint8_t *twi_ptr;
26
static uint32_t twi_mask;
29
static uint8_t out_buff[BUF_SIZE];
31
static void systick_wait_ns(uint32_t ns) {
32
uint32_t x = (ns >> 7) + 1;
38
static void twi_reset(void) {
41
REG_STORE(AT91C_TWI_IDR, ~0);
43
REG_STORE(AT91C_PMC_PCER, (1 << AT91C_ID_PIOA) | /* Need PIO too */
44
(1 << AT91C_ID_TWI)); /* TWI clock domain */
46
/* MAGIC Set up pin as an IO pin for clocking till clean */
47
/* Why we need to clock? */
48
REG_STORE(AT91C_PIOA_MDER, AT91C_PA3_TWD | AT91C_PA4_TWCK);
49
REG_STORE(AT91C_PIOA_PER, AT91C_PA3_TWD | AT91C_PA4_TWCK);
50
REG_STORE(AT91C_PIOA_ODR, AT91C_PA3_TWD);
51
REG_STORE(AT91C_PIOA_OER, AT91C_PA4_TWCK);
53
while (clocks > 0 && !(REG_LOAD(AT91C_PIOA_PDSR) & AT91C_PA3_TWD)) {
54
REG_STORE(AT91C_PIOA_CODR, AT91C_PA4_TWCK);
55
systick_wait_ns(1500);
56
REG_STORE(AT91C_PIOA_SODR, AT91C_PA4_TWCK);
57
systick_wait_ns(1500);
61
REG_STORE(AT91C_PIOA_PDR, AT91C_PA3_TWD | AT91C_PA4_TWCK);
62
REG_STORE(AT91C_PIOA_ASR, AT91C_PA3_TWD | AT91C_PA4_TWCK);
66
REG_STORE(AT91C_TWI_CR, AT91C_TWI_SWRST | AT91C_TWI_MSDIS);
69
REG_STORE(AT91C_TWI_CWGR, ((CLDIV << 8) | CLDIV));
70
/* Enable as master */
71
REG_STORE(AT91C_TWI_CR, AT91C_TWI_MSEN);
72
//*AT91C_TWI_IER = AT91C_TWI_NACK;
76
static int twi_init(void) {
81
void twi_write(uint32_t dev_addr, const uint8_t *data, uint32_t nBytes) {
82
twi_ptr = (uint8_t *) data;
85
REG_STORE(AT91C_TWI_MMR, AT91C_TWI_IADRSZ_NO | ((dev_addr & 0x7f) << 16));
87
REG_STORE(AT91C_TWI_THR, *twi_ptr++);
90
while (twi_pending > 0) {
91
while (!(REG_LOAD(AT91C_TWI_SR) & AT91C_TWI_TXRDY));
92
REG_STORE(AT91C_TWI_THR, *twi_ptr++);
96
while (!(REG_LOAD(AT91C_TWI_SR) & AT91C_TWI_TXCOMP));
99
void twi_send(uint32_t dev_addr, const uint8_t *data, uint32_t count) {
100
const uint8_t *sptr = data;
101
uint8_t *dptr = out_buff;
102
uint8_t checkbyte = 0;
103
uint32_t left_count = count;
105
if (count >= BUF_SIZE) {
106
panic("Sending to AVR abnormal long data\n");
109
while (left_count-- > 0) {
115
twi_write(dev_addr, out_buff, count + 1);
118
int twi_receive(uint32_t dev_addr, uint8_t *data, uint32_t count) {
120
uint8_t checkbyte = 0;
122
REG_STORE(AT91C_TWI_MMR, AT91C_TWI_IADRSZ_NO |
123
AT91C_TWI_MREAD | ((dev_addr & 0x7f) << 16));
124
REG_STORE(AT91C_TWI_CR, AT91C_TWI_START);
126
while (count-- > 1) {
127
while (!(REG_LOAD(AT91C_TWI_SR) & AT91C_TWI_RXRDY));
129
*ptr = REG_LOAD(AT91C_TWI_RHR);
134
REG_STORE(AT91C_TWI_CR, AT91C_TWI_STOP);
136
while (!(REG_LOAD(AT91C_TWI_SR) & AT91C_TWI_RXRDY)) {
140
*ptr = REG_LOAD(AT91C_TWI_RHR);
143
while (!(REG_LOAD(AT91C_TWI_SR) & AT91C_TWI_TXCOMP)) {
147
return ((checkbyte == 0xff) ? 1 : 0);