Change bootloader makefiles to automatically compute the bootloader starting address...
[pub/USBasp.git] / LUFA / Drivers / Peripheral / TWI.c
1 /*
2 Copyright (C) Dean Camera, 2011.
3
4 dean [at] fourwalledcubicle [dot] com
5 www.lufa-lib.org
6 */
7
8 #include "TWI.h"
9
10 uint8_t TWI_StartTransmission(const uint8_t SlaveAddress,
11 const uint8_t TimeoutMS)
12 {
13 for (;;)
14 {
15 bool BusCaptured = false;
16 uint16_t TimeoutRemaining;
17
18 TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
19
20 TimeoutRemaining = (TimeoutMS * 100);
21 while (TimeoutRemaining-- && !(BusCaptured))
22 {
23 if (TWCR & (1 << TWINT))
24 {
25 switch (TWSR & TW_STATUS_MASK)
26 {
27 case TW_START:
28 case TW_REP_START:
29 BusCaptured = true;
30 break;
31 case TW_MT_ARB_LOST:
32 TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
33 continue;
34 default:
35 TWCR = (1 << TWEN);
36 return TWI_ERROR_BusFault;
37 }
38 }
39
40 _delay_us(10);
41 }
42
43 if (!(TimeoutRemaining))
44 {
45 TWCR = (1 << TWEN);
46 return TWI_ERROR_BusCaptureTimeout;
47 }
48
49 TWDR = SlaveAddress;
50 TWCR = ((1 << TWINT) | (1 << TWEN));
51
52 TimeoutRemaining = (TimeoutMS * 100);
53 while (TimeoutRemaining--)
54 {
55 if (TWCR & (1 << TWINT))
56 break;
57
58 _delay_us(10);
59 }
60
61 if (!(TimeoutRemaining))
62 return TWI_ERROR_SlaveResponseTimeout;
63
64 switch (TWSR & TW_STATUS_MASK)
65 {
66 case TW_MT_SLA_ACK:
67 case TW_MR_SLA_ACK:
68 return TWI_ERROR_NoError;
69 default:
70 TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN));
71 return TWI_ERROR_SlaveNotReady;
72 }
73 }
74 }
75
76 uint8_t TWI_ReadPacket(const uint8_t SlaveAddress,
77 const uint8_t TimeoutMS,
78 const uint8_t* InternalAddress,
79 uint8_t InternalAddressLen,
80 uint8_t* Buffer,
81 uint8_t Length)
82 {
83 uint8_t ErrorCode;
84
85 if ((ErrorCode = TWI_WritePacket(SlaveAddress, TimeoutMS, InternalAddress, InternalAddressLen,
86 NULL, 0)) != TWI_ERROR_NoError)
87 {
88 return ErrorCode;
89 }
90
91 if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_READ,
92 TimeoutMS)) == TWI_ERROR_NoError)
93 {
94 while (Length--)
95 {
96 if (!(TWI_ReceiveByte(Buffer++, (Length == 0))))
97 {
98 ErrorCode = TWI_ERROR_SlaveNAK;
99 break;
100 }
101 }
102
103 TWI_StopTransmission();
104 }
105
106 return ErrorCode;
107 }
108
109 uint8_t TWI_WritePacket(const uint8_t SlaveAddress,
110 const uint8_t TimeoutMS,
111 const uint8_t* InternalAddress,
112 uint8_t InternalAddressLen,
113 const uint8_t* Buffer,
114 uint8_t Length)
115 {
116 uint8_t ErrorCode;
117
118 if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
119 TimeoutMS)) == TWI_ERROR_NoError)
120 {
121 while (InternalAddressLen--)
122 {
123 if (!(TWI_SendByte(*(InternalAddress++))))
124 {
125 ErrorCode = TWI_ERROR_SlaveNAK;
126 break;
127 }
128 }
129
130 while (Length--)
131 {
132 if (!(TWI_SendByte(*(Buffer++))))
133 {
134 ErrorCode = TWI_ERROR_SlaveNAK;
135 break;
136 }
137 }
138
139 TWI_StopTransmission();
140 }
141
142 return ErrorCode;
143 }