Subversion Repositories NaviCtrl

Rev

Rev 508 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
482 killagreg 1
/*#######################################################################################*/
2
/* !!! THIS IS NOT FREE SOFTWARE !!!                                                     */
3
/*#######################################################################################*/
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5
// + www.MikroKopter.com
6
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7
// + Software Nutzungsbedingungen (english version: see below)
8
// + der Fa. HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland - nachfolgend Lizenzgeber genannt -
9
// + Der Lizenzgeber räumt dem Kunden ein nicht-ausschließliches, zeitlich und räumlich* unbeschränktes Recht ein, die im den
10
// + Mikrocontroller verwendete Firmware für die Hardware Flight-Ctrl, Navi-Ctrl, BL-Ctrl, MK3Mag & PC-Programm MikroKopter-Tool 
11
// + - nachfolgend Software genannt - nur für private Zwecke zu nutzen.
12
// + Der Einsatz dieser Software ist nur auf oder mit Produkten des Lizenzgebers zulässig.
13
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
14
// + Die vom Lizenzgeber gelieferte Software ist urheberrechtlich geschützt. Alle Rechte an der Software sowie an sonstigen im
15
// + Rahmen der Vertragsanbahnung und Vertragsdurchführung überlassenen Unterlagen stehen im Verhältnis der Vertragspartner ausschließlich dem Lizenzgeber zu.
16
// + Die in der Software enthaltenen Copyright-Vermerke, Markenzeichen, andere Rechtsvorbehalte, Seriennummern sowie
17
// + sonstige der Programmidentifikation dienenden Merkmale dürfen vom Kunden nicht verändert oder unkenntlich gemacht werden.
18
// + Der Kunde trifft angemessene Vorkehrungen für den sicheren Einsatz der Software. Er wird die Software gründlich auf deren
19
// + Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
20
// + Die Haftung des Lizenzgebers wird - soweit gesetzlich zulässig - begrenzt in Höhe des typischen und vorhersehbaren
21
// + Schadens. Die gesetzliche Haftung bei Personenschäden und nach dem Produkthaftungsgesetz bleibt unberührt. Dem Lizenzgeber steht jedoch der Einwand 
22
// + des Mitverschuldens offen.
23
// + Der Kunde trifft angemessene Vorkehrungen für den Fall, dass die Software ganz oder teilweise nicht ordnungsgemäß arbeitet.
24
// + Er wird die Software gründlich auf deren Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
25
// + Der Kunde wird er seine Daten vor Einsatz der Software nach dem Stand der Technik sichern.
26
// + Der Kunde ist darüber unterrichtet, dass der Lizenzgeber seine Daten im zur Vertragsdurchführung erforderlichen Umfang
27
// + und auf Grundlage der Datenschutzvorschriften erhebt, speichert, verarbeitet und, sofern notwendig, an Dritte übermittelt.
28
// + *) Die räumliche Nutzung bezieht sich nur auf den Einsatzort, nicht auf die Reichweite der programmierten Software.
29
// + #### ENDE DER NUTZUNGSBEDINGUNGEN ####'
30
// +  Hinweis: Informationen über erweiterte Nutzungsrechte (wie z.B. Nutzung für nicht-private Zwecke) sind auf Anfrage per Email an info(@)hisystems.de verfügbar.
31
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
32
// + Software LICENSING TERMS
33
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34
// + of HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland, Germany - the Licensor -
35
// + The Licensor grants the customer a non-exclusive license to use the microcontroller firmware of the Flight-Ctrl, Navi-Ctrl, BL-Ctrl, and MK3Mag hardware 
36
// + (the Software) exclusively for private purposes. The License is unrestricted with respect to time and territory*.
37
// + The Software may only be used with the Licensor's products.
38
// + The Software provided by the Licensor is protected by copyright. With respect to the relationship between the parties to this
39
// + agreement, all rights pertaining to the Software and other documents provided during the preparation and execution of this
40
// + agreement shall be the property of the Licensor.
41
// + The information contained in the Software copyright notices, trademarks, other legal reservations, serial numbers and other
42
// + features that can be used to identify the program may not be altered or defaced by the customer.
43
// + The customer shall be responsible for taking reasonable precautions
44
// + for the safe use of the Software. The customer shall test the Software thoroughly regarding its suitability for the
45
// + intended purpose before implementing it for actual operation. The Licensor's liability shall be limited to the extent of typical and
46
// + foreseeable damage to the extent permitted by law, notwithstanding statutory liability for bodily injury and product
47
// + liability. However, the Licensor shall be entitled to the defense of contributory negligence.
48
// + The customer will take adequate precautions in the case, that the software is not working properly. The customer will test
49
// + the software for his purpose before any operational usage. The customer will backup his data before using the software.
50
// + The customer understands that the Licensor collects, stores and processes, and, where required, forwards, customer data
51
// + to third parties to the extent necessary for executing the agreement, subject to applicable data protection and privacy regulations.
52
// + *) The territory aspect only refers to the place where the Software is used, not its programmed range.
53
// + #### END OF LICENSING TERMS ####
54
// + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de.
55
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56
#include <string.h>
57
#include "i2c.h"
58
#include "uart1.h"
59
#include "timer1.h"
60
#include "config.h"
61
#include "led.h"
62
 
63
// the transfer buffer
64
u8 I2C0_Buffer[I2C_BUFFER_LEN];
65
u8 I2C1_Buffer[I2C_BUFFER_LEN];
66
 
67
volatile I2C_Bus_t I2C0_Bus;
68
volatile I2C_Bus_t I2C1_Bus;
69
 
70
// Retourns pointer to data structure of the selected bus 
71
volatile I2C_Bus_t* I2CBus(I2C_TypeDef* I2Cx)
72
{
73
        volatile I2C_Bus_t *pBus = NULL;
74
 
75
        if(I2Cx == I2C0) pBus = &I2C0_Bus;
76
        if(I2Cx == I2C1) pBus = &I2C1_Bus;
77
 
78
        return(pBus);
79
}
80
 
81
//--------------------------------------------------------------
82
void I2CBus_Init(I2C_TypeDef* I2Cx)
83
{
84
        volatile  I2C_Bus_t *pBus = NULL;
85
        I2C_InitTypeDef   I2C_Struct;
86
        GPIO_InitTypeDef  GPIO_InitStructure;
87
        u8 SCL_Pin = 0;
88
        u8 SDA_Pin = 0;
89
        u32 SCL_Clock = 0;
90
        u32 APBPeriph = 0;
91
        u8 VIC_Priority = 0;
92
 
93
        if (I2Cx == I2C0)
94
        {
95
                UART1_PutString("\r\n I2C0 init...");
96
                SCL_Pin = GPIO_Pin_0;
97
                SDA_Pin = GPIO_Pin_1;
98
                SCL_Clock = I2C0_CLOCK;
99
                APBPeriph = __I2C0;
100
                VIC_Priority = PRIORITY_I2C0;
101
 
102
                pBus = &I2C0_Bus;
103
                pBus->pData = I2C0_Buffer;
104
                pBus->VIC_Source = I2C0_ITLine;        
105
        }
106
        if (I2Cx == I2C1)      
107
        {
108
                UART1_PutString("\r\n I2C1 init...");
109
                SCL_Pin = GPIO_Pin_2;
110
                SDA_Pin = GPIO_Pin_3;
111
                SCL_Clock = I2C1_CLOCK;
112
                APBPeriph = __I2C1;
113
                VIC_Priority = PRIORITY_I2C1;
114
 
115
                pBus = &I2C1_Bus;
116
                pBus->pData = I2C1_Buffer;
117
                pBus->VIC_Source = I2C1_ITLine;        
118
        }
119
        if(pBus == NULL) return;
120
 
121
        pBus->State = I2C_STATE_UNDEF;
122
        pBus->Error = I2C_ERROR_UNKNOWN;
123
        pBus->Timeout = 0;
124
        pBus->TxBufferSize = 0;
125
        pBus->RxBufferSize = 0;
126
        pBus->Direction = 0;
127
        pBus->SlaveAddr = 0;
128
        pBus->pRxHandler = NULL;
129
 
130
        // enable Port 2 peripherie
131
        SCU_APBPeriphClockConfig(__GPIO2, ENABLE);
132
        // disable a reset state
133
        SCU_APBPeriphReset(__GPIO2, DISABLE);
134
 
135
        // free a busy bus
136
 
137
        // At switch on I2C devices can get in a state where they
138
        // are still waiting for a command due to all the bus lines bouncing
139
        // around at startup have started clocking data into the device(s).
140
        // Enable the ports as open collector port outputs
141
        // and clock out at least 9 SCL pulses, then generate a stop
142
        // condition and then leave the clock line high.
143
 
144
        // configure I2C_CLKOUT and I2C_DOUT to normal port operation
145
        GPIO_StructInit(&GPIO_InitStructure);
146
        GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
147
        GPIO_InitStructure.GPIO_Pin = SCL_Pin | SDA_Pin;
148
        GPIO_InitStructure.GPIO_Type = GPIO_Type_OpenCollector;
149
        GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable;
150
        GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1;
151
        GPIO_Init(GPIO2, &GPIO_InitStructure);
152
 
153
        u8 i;
154
        u32 delay;
155
        // set SCL high and then SDA to low (start condition)
156
        GPIO_WriteBit(GPIO2, SCL_Pin, Bit_SET);
157
        delay = SetDelay(1);
158
        while (!CheckDelay(delay));
159
        GPIO_WriteBit(GPIO2, SDA_Pin, Bit_RESET);
160
        // toggle SCL at least 10 times from high to low to high
161
        for(i = 0; i < 10; i++)
162
        {
163
                delay = SetDelay(1);
164
                while (!CheckDelay(delay));
165
 
166
                GPIO_WriteBit(GPIO2, SCL_Pin, Bit_RESET);
167
                delay = SetDelay(1);
168
                while (!CheckDelay(delay));
169
                GPIO_WriteBit(GPIO2, SCL_Pin, Bit_SET);
170
        }
171
        delay = SetDelay(1);
172
        while (!CheckDelay(delay));
173
        // create stop condition setting SDA HIGH when SCL is HIGH
174
        GPIO_WriteBit(GPIO2, SDA_Pin, Bit_SET);
175
 
176
 
177
        // reconfigure I2C_CLKOUT and I2C_DOUT
178
        GPIO_StructInit(&GPIO_InitStructure);
179
        GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
180
        GPIO_InitStructure.GPIO_Pin = SCL_Pin | SDA_Pin;
181
        GPIO_InitStructure.GPIO_Type = GPIO_Type_OpenCollector;
182
        GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Enable;
183
        GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2; //I2C_CLKOUT, I2C_DOUT
184
        GPIO_Init(GPIO2, &GPIO_InitStructure);
185
 
186
        // enable I2C peripherie
187
        SCU_APBPeriphClockConfig(APBPeriph, ENABLE);
188
        // reset I2C peripherie
189
        SCU_APBPeriphReset(APBPeriph, ENABLE);
190
        SCU_APBPeriphReset(APBPeriph, DISABLE);
191
 
192
        I2C_DeInit(I2Cx);
193
        I2C_StructInit(&I2C_Struct);
194
        I2C_Struct.I2C_GeneralCall = I2C_GeneralCall_Disable;
195
        I2C_Struct.I2C_Ack = I2C_Ack_Enable;
196
        I2C_Struct.I2C_CLKSpeed = SCL_Clock;
197
        I2C_Struct.I2C_OwnAddress = 0x00;
198
        I2C_Init(I2Cx, &I2C_Struct);
199
 
200
        I2C_Cmd(I2Cx, ENABLE);
201
        I2C_ITConfig(I2Cx, ENABLE);
202
 
203
        VIC_Config(pBus->VIC_Source, VIC_IRQ , VIC_Priority);
204
        pBus->Timeout = SetDelay(2*I2C_TIMEOUT);
205
        I2C_GenerateSTOP(I2Cx, ENABLE);
206
        pBus->State = I2C_STATE_IDLE;
207
 
208
        // start some dummy transmissions cycles
209
        // to get the irq routine to work
210
        for(i = 0; i < 10; i++)
211
        {
212
                pBus->State = I2C_STATE_BUFFBUSY;
213
                I2CBus_Transmission(I2Cx, 0, NULL, 1, 0, 0); // transfer 1 byte in the isr
214
                if(I2CBus_WaitForEndOfTransmission(I2Cx, 10)) break;
215
                UART1_Putchar('.');
216
        }
217
        UART1_PutString("ok");
218
}
219
 
220
 
221
//--------------------------------------------------------------
222
void I2CBus_Deinit(I2C_TypeDef* I2Cx)
223
{
224
        volatile I2C_Bus_t *pBus = NULL;
225
        GPIO_InitTypeDef  GPIO_InitStructure;
226
        u32 APBPeriph = 0;
227
        u16 VIC_Source = 0;
228
        u8      SCL_Pin = 0;
229
        u8  SDA_Pin = 0;
230
 
231
        if (I2Cx == I2C0)
232
        {
233
                UART1_PutString("\r\n I2C0 deinit...");
234
                SCL_Pin = GPIO_Pin_0;
235
                SDA_Pin = GPIO_Pin_1;
236
                APBPeriph = __I2C0;
237
                VIC_Source = I2C0_ITLine;
238
                pBus = &I2C0_Bus;
239
 
240
        }
241
        if (I2Cx == I2C1)
242
        {
243
                UART1_PutString("\r\n I2C1 deinit...");
244
                SCL_Pin = GPIO_Pin_2;
245
                SDA_Pin = GPIO_Pin_3;
246
                APBPeriph = __I2C1;
247
                VIC_Source = I2C1_ITLine;
248
                pBus = &I2C1_Bus;
249
        }
250
 
251
        if(pBus == NULL) return;
252
 
253
        I2C_GenerateStart(I2Cx, DISABLE);
254
        I2C_GenerateSTOP(I2Cx, ENABLE);
255
        VIC_ITCmd(VIC_Source, DISABLE);
256
        pBus->State = I2C_STATE_UNDEF;
257
        I2C_ITConfig(I2Cx, DISABLE);
258
        I2C_Cmd(I2Cx, DISABLE);
259
        I2C_DeInit(I2Cx);
260
        SCU_APBPeriphClockConfig(APBPeriph, DISABLE);
261
 
262
        // set ports to input
263
        SCU_APBPeriphClockConfig(__GPIO2, ENABLE);
264
        GPIO_StructInit(&GPIO_InitStructure);
265
        GPIO_InitStructure.GPIO_Direction =     GPIO_PinInput;
266
        GPIO_InitStructure.GPIO_Pin =                   SCL_Pin | SDA_Pin;
267
        GPIO_InitStructure.GPIO_Type =                  GPIO_Type_PushPull;
268
        GPIO_InitStructure.GPIO_IPInputConnected =      GPIO_IPInputConnected_Disable;
269
        GPIO_InitStructure.GPIO_Alternate =     GPIO_InputAlt1;
270
        GPIO_Init(GPIO2, &GPIO_InitStructure);
271
 
272
        // empty rx and tx buffer
273
        pBus->TxBufferSize = 0;
274
        pBus->RxBufferSize = 0;
275
 
276
        pBus->Timeout = SetDelay(2*I2C_TIMEOUT);
277
 
278
        UART1_PutString("ok");
279
}
280
 
281
//--------------------------------------------------------------
282
void I2C0_IRQHandler(void)
283
{
284
        static u8 Rx_Idx = 0, Tx_Idx = 0;
285
        u16 status;
286
        u16 timeout = 500;
287
 
288
        //IENABLE;  // do not enable IRQ nesting for I2C!!!!
289
        // detemine I2C State
290
        status = I2C_GetLastEvent(I2C0);
291
 
292
        if(status & (I2C_FLAG_AF|I2C_FLAG_BERR))  // if an acknowledge failure or bus error occured
293
        {       // Set and subsequently clear the STOP bit while BTF is set.
294
                while(I2C_GetFlagStatus (I2C0, I2C_FLAG_BTF) != RESET)
295
                {
296
                        I2C_GenerateSTOP (I2C0, ENABLE);  // free the bus
297
                        I2C_GenerateSTOP (I2C0, DISABLE); // free the bus
298
                        if(--timeout == 0)
299
                        {
300
                                DebugOut.Analog[14]++; // count I2C error
301
                                break;
302
                        }
303
                }
304
                I2C0_Bus.State = I2C_STATE_IDLE;
305
                I2C0_Bus.Error = I2C_ERROR_NOACK;
306
                VIC_ITCmd(I2C0_ITLine, DISABLE);
307
                return;
308
        }
309
        else
310
        {       // depending on current i2c state
311
                switch(status)
312
                {
313
                        // the start condition was initiated on the bus
314
                        case I2C_EVENT_MASTER_MODE_SELECT:
315
                                // update current bus state variable
316
                                // jump to rx state if there is nothing to send
317
                                switch(I2C0_Bus.Direction)
318
                                {
319
                                        case I2C_MODE_TRANSMITTER:
320
                                                I2C0_Bus.State = I2C_STATE_TX_PROGRESS;
321
                                                break;
322
 
323
                                        case I2C_MODE_RECEIVER:
324
                                                if (I2C0_Bus.RxBufferSize == 0) // nothing to send?
325
                                                {
326
                                                        I2C_GenerateSTOP (I2C0, ENABLE);
327
                                                        VIC_ITCmd(I2C0_ITLine, DISABLE);
328
                                                        I2C0_Bus.State = I2C_STATE_IDLE;
329
                                                        I2C1_Bus.Error = I2C_ERROR_NONE;
330
                                                        return;
331
                                                }
332
                                                else
333
                                                {
334
                                                        I2C0_Bus.State = I2C_STATE_RX_PROGRESS;
335
                                                }
336
                                                break;
337
 
338
                                        default: // invalid direction
339
                                                I2C_GenerateSTOP (I2C0, ENABLE);
340
                                                VIC_ITCmd(I2C0_ITLine, DISABLE);
341
                                                I2C1_Bus.State = I2C_STATE_IDLE;
342
                                                I2C1_Bus.Error = I2C_ERROR_UNKNOWN;
343
                                                return;
344
                                }
345
                                // enable acknowledge
346
                                I2C_AcknowledgeConfig (I2C0, ENABLE);
347
                                // send address/direction byte on the bus
348
                                I2C_Send7bitAddress(I2C0, I2C0_Bus.SlaveAddr, I2C0_Bus.Direction);
349
                                break;
350
 
351
                        // the address byte was send
352
                        case I2C_EVENT_MASTER_MODE_SELECTED:
353
                                // Clear EV6 by set again the PE bit
354
                                I2C_Cmd(I2C0, ENABLE);
355
                                switch(I2C0_Bus.State)
356
                                {
357
                                        case I2C_STATE_TX_PROGRESS:
358
                                        // send 1st data byte
359
                                        Tx_Idx = 0;
360
                                        I2C_SendData(I2C0, I2C0_Bus.pData[Tx_Idx]);
361
                                        Tx_Idx++;
362
                                        // reset timeout
363
                                        I2C0_Bus.Timeout = SetDelay(I2C_TIMEOUT); // after inactivity the I2C1 bus will be reset
364
                                        break;
365
 
366
                                        case I2C_STATE_RX_PROGRESS:
367
                                        Rx_Idx = 0;
368
                                        // disable acknoledge if only one byte has to be read
369
                                        if(I2C0_Bus.RxBufferSize == 1) I2C_AcknowledgeConfig (I2C0, DISABLE);          
370
                                        break;
371
 
372
                                        default: // unknown I2C state
373
                                        // should never happen
374
                                        I2C_GenerateSTOP (I2C0, ENABLE);
375
                                        VIC_ITCmd(I2C0_ITLine, DISABLE);
376
                                        I2C0_Bus.State = I2C_STATE_IDLE;
377
                                        I2C0_Bus.Error = I2C_ERROR_UNKNOWN;
378
                                        return;
379
                                        break;
380
                                }
381
                                break;
382
 
383
                        // the master has transmitted a byte and slave has been acknowledged
384
                        case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
385
 
386
                                // some bytes have to be transmitted
387
                                if(Tx_Idx < I2C0_Bus.TxBufferSize)
388
                                {
389
                                        I2C_SendData(I2C0, I2C0_Bus.pData[Tx_Idx]);
390
                                        Tx_Idx++;
391
                                }
392
                                else // last byte was send
393
                                {
394
                                        // generate stop or repeated start condition
395
                                        if (I2C0_Bus.RxBufferSize > 0) // is any answer byte expected?
396
                                        {
397
                                                I2C0_Bus.Direction = I2C_MODE_RECEIVER; // switch to master receiver after repeated start condition
398
                                                I2C_GenerateStart(I2C0, ENABLE);   // initiate repeated start condition on the bus
399
                                        }
400
                                        else
401
                                        {   // stop communication
402
                                                I2C_GenerateSTOP(I2C0, ENABLE); // generate stop condition to free the bus
403
                                                VIC_ITCmd(I2C0_ITLine, DISABLE);
404
                                                I2C0_Bus.State = I2C_STATE_IDLE;                        // ready for new actions
405
                                                I2C0_Bus.Error = I2C_ERROR_NONE;       
406
                                        }
407
                                }
408
                                break;
409
 
410
                        // the master has received a byte from the slave
411
                        case I2C_EVENT_MASTER_BYTE_RECEIVED:
412
                                // some bytes have to be received
413
                                if ( Rx_Idx+1 < I2C0_Bus.RxBufferSize)
414
                                {       // copy received byte  from the data register to the rx-buffer
415
                                        I2C0_Bus.pData[Rx_Idx] = I2C_ReceiveData(I2C0);
416
                                }
417
                                else // if the last byte was received
418
                                {
419
                                        // generate a STOP condition on the bus before reading data register
420
                                        I2C_GenerateSTOP(I2C0, ENABLE);
421
                                        I2C0_Bus.pData[Rx_Idx] = I2C_ReceiveData(I2C0);
422
                                        // call the rx handler function to process recieved data
423
                                        if(I2C0_Bus.pRxHandler != NULL) (*(I2C0_Bus.pRxHandler))(I2C0_Bus.pData, I2C0_Bus.RxBufferSize);
424
                                        I2C0_Bus.Timeout = SetDelay(I2C_TIMEOUT);
425
                                        DebugOut.Analog[15]++;
426
                                        VIC_ITCmd(I2C0_ITLine, DISABLE);
427
                                        I2C0_Bus.State = I2C_STATE_IDLE;
428
                                        I2C0_Bus.Error = I2C_ERROR_NONE;
429
                                        return;
430
                                }
431
                                Rx_Idx++;
432
                                // if the 2nd last byte was received disable acknowledge for the last one
433
                                if ( (Rx_Idx + 1) == I2C0_Bus.RxBufferSize )
434
                                {
435
                                        I2C_AcknowledgeConfig(I2C0, DISABLE);
436
                                }
437
                                break;
438
 
439
                        default:// unknown event
440
                                // should never happen
441
                                I2C_GenerateSTOP (I2C0, ENABLE);
442
                                VIC_ITCmd(I2C0_ITLine, DISABLE);
443
                                I2C0_Bus.State = I2C_STATE_IDLE;
444
                                I2C0_Bus.Error = I2C_ERROR_UNKNOWN;
445
                                break;
446
                }
447
        }
448
        //IDISABLE;      // do not enable IRQ nesting for I2C!!!!
449
        VIC1->VAR = 0xFF; // write any value to VIC1 Vector address register
450
}
451
 
452
//--------------------------------------------------------------
453
void I2C1_IRQHandler(void)
454
{
455
        static u8 Rx_Idx = 0, Tx_Idx = 0;
456
        u16 status;
457
        u16 timeout = 500;
458
 
459
        //IENABLE;  // do not enable IRQ nesting for I2C!!!!
460
        // detemine I2C State
461
        status = I2C_GetLastEvent(I2C1);
462
 
463
        if(status & (I2C_FLAG_AF|I2C_FLAG_BERR))  // if an acknowledge failure or bus error occured
464
        {       // Set and subsequently clear the STOP bit while BTF is set.
465
                while(I2C_GetFlagStatus (I2C1, I2C_FLAG_BTF) != RESET)
466
                {
467
                        I2C_GenerateSTOP (I2C1, ENABLE);  // free the bus
468
                        I2C_GenerateSTOP (I2C1, DISABLE); // free the bus
469
                        if(--timeout == 0)
470
                        {
471
                                DebugOut.Analog[14]++; // count I2C error
472
                                break;
473
                        }
474
                }
475
                I2C1_Bus.State = I2C_STATE_IDLE;
476
                I2C1_Bus.Error = I2C_ERROR_NOACK;
477
                VIC_ITCmd(I2C1_ITLine, DISABLE);
478
                return;
479
        }
480
        else
481
        {       // depending on current i2c state
482
                switch(status)
483
                {
484
                        // the start condition was initiated on the bus
485
                        case I2C_EVENT_MASTER_MODE_SELECT:
486
                                // update current bus state variable
487
                                // jump to rx state if there is nothing to send
488
                                switch(I2C1_Bus.Direction)
489
                                {
490
                                        case I2C_MODE_TRANSMITTER:
491
                                                I2C1_Bus.State = I2C_STATE_TX_PROGRESS;
492
                                                break;
493
 
494
                                        case I2C_MODE_RECEIVER:
495
                                                if (I2C1_Bus.RxBufferSize == 0) // nothing to send?
496
                                                {
497
                                                        I2C_GenerateSTOP (I2C1, ENABLE);
498
                                                        VIC_ITCmd(I2C1_ITLine, DISABLE);
499
                                                        I2C1_Bus.State = I2C_STATE_IDLE;
500
                                                        I2C1_Bus.Error = I2C_ERROR_NONE;
501
                                                        return;
502
                                                }
503
                                                else
504
                                                {
505
                                                        I2C1_Bus.State = I2C_STATE_RX_PROGRESS;
506
                                                }
507
                                                break;
508
 
509
                                        default: // invalid direction
510
                                                I2C_GenerateSTOP (I2C1, ENABLE);
511
                                                VIC_ITCmd(I2C1_ITLine, DISABLE);
512
                                                I2C1_Bus.State = I2C_STATE_IDLE;
513
                                                I2C1_Bus.Error = I2C_ERROR_UNKNOWN;
514
                                                return;
515
                                }
516
                                // enable acknowledge
517
                                I2C_AcknowledgeConfig (I2C1, ENABLE);
518
                                // send address/direction byte on the bus
519
                                I2C_Send7bitAddress(I2C1, I2C1_Bus.SlaveAddr, I2C1_Bus.Direction);
520
                                break;
521
 
522
                        // the address byte was send
523
                        case I2C_EVENT_MASTER_MODE_SELECTED:
524
                                // Clear EV6 by set again the PE bit
525
                                I2C_Cmd(I2C1, ENABLE);
526
                                switch(I2C1_Bus.State)
527
                                {
528
                                        case I2C_STATE_TX_PROGRESS:
529
                                        // send 1st data byte
530
                                        Tx_Idx = 0;
531
                                        I2C_SendData(I2C1, I2C1_Bus.pData[Tx_Idx]);
532
                                        Tx_Idx++;
533
                                        // reset timeout
534
                                        I2C1_Bus.Timeout = SetDelay(I2C_TIMEOUT); // after inactivity the I2C1 bus will be reset
535
                                        break;
536
 
537
                                        case I2C_STATE_RX_PROGRESS:
538
                                        Rx_Idx = 0;
539
                                        // disable acknoledge if only one byte has to be read
540
                                        if(I2C1_Bus.RxBufferSize == 1) I2C_AcknowledgeConfig (I2C1, DISABLE);          
541
                                        break;
542
 
543
                                        default: // unknown I2C state
544
                                        // should never happen
545
                                        I2C_GenerateSTOP (I2C1, ENABLE);
546
                                        VIC_ITCmd(I2C1_ITLine, DISABLE);
547
                                        I2C1_Bus.State = I2C_STATE_IDLE;
548
                                        I2C1_Bus.Error = I2C_ERROR_UNKNOWN;
549
                                        return;
550
                                        break;
551
                                }
552
                                break;
553
 
554
                        // the master has transmitted a byte and slave has been acknowledged
555
                        case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
556
 
557
                                // some bytes have to be transmitted
558
                                if(Tx_Idx < I2C1_Bus.TxBufferSize)
559
                                {
560
                                        I2C_SendData(I2C1, I2C1_Bus.pData[Tx_Idx]);
561
                                        Tx_Idx++;
562
                                }
563
                                else // last byte was send
564
                                {
565
                                        // generate stop or repeated start condition
566
                                        if (I2C1_Bus.RxBufferSize > 0) // is any answer byte expected?
567
                                        {
568
                                                I2C1_Bus.Direction = I2C_MODE_RECEIVER; // switch to master receiver after repeated start condition
569
                                                I2C_GenerateStart(I2C1, ENABLE);   // initiate repeated start condition on the bus
570
                                        }
571
                                        else
572
                                        {   // stop communication
573
                                                I2C_GenerateSTOP(I2C1, ENABLE); // generate stop condition to free the bus
574
                                                VIC_ITCmd(I2C1_ITLine, DISABLE);
575
                                                I2C1_Bus.State = I2C_STATE_IDLE;                        // ready for new actions
576
                                                I2C1_Bus.Error = I2C_ERROR_NONE;       
577
                                        }
578
                                }
579
                                break;
580
 
581
                        // the master has received a byte from the slave
582
                        case I2C_EVENT_MASTER_BYTE_RECEIVED:
583
                                // some bytes have to be received
584
                                if ( Rx_Idx+1 < I2C1_Bus.RxBufferSize)
585
                                {       // copy received byte  from the data register to the rx-buffer
586
                                        I2C1_Bus.pData[Rx_Idx] = I2C_ReceiveData(I2C1);
587
                                }
588
                                else // if the last byte was received
589
                                {
590
                                        // generate a STOP condition on the bus before reading data register
591
                                        I2C_GenerateSTOP(I2C1, ENABLE);
592
                                        I2C1_Bus.pData[Rx_Idx] = I2C_ReceiveData(I2C1);
593
                                        // call the rx handler function to process recieved data
594
                                        if(I2C1_Bus.pRxHandler != NULL) (*(I2C1_Bus.pRxHandler))(I2C1_Bus.pData, I2C1_Bus.RxBufferSize);
595
                                        I2C1_Bus.Timeout = SetDelay(I2C_TIMEOUT);
596
                                        DebugOut.Analog[15]++;
597
                                        VIC_ITCmd(I2C1_ITLine, DISABLE);
598
                                        I2C1_Bus.State = I2C_STATE_IDLE;
599
                                        I2C1_Bus.Error = I2C_ERROR_NONE;
600
                                        return;
601
                                }
602
                                Rx_Idx++;
603
                                // if the 2nd last byte was received disable acknowledge for the last one
604
                                if ( (Rx_Idx + 1) == I2C1_Bus.RxBufferSize )
605
                                {
606
                                        I2C_AcknowledgeConfig(I2C1, DISABLE);
607
                                }
608
                                break;
609
 
610
                        default:// unknown event
611
                                // should never happen
508 holgerb 612
                                DebugOut.Analog[14]++;
482 killagreg 613
                                I2C_GenerateSTOP (I2C1, ENABLE);
614
                                VIC_ITCmd(I2C1_ITLine, DISABLE);
615
                                I2C1_Bus.State = I2C_STATE_IDLE;
616
                                I2C1_Bus.Error = I2C_ERROR_UNKNOWN;
617
                                break;
618
                }
619
        }
620
        //IDISABLE;      // do not enable IRQ nesting for I2C!!!!
621
        VIC1->VAR = 0xFF; // write any value to VIC1 Vector address register
622
}
623
 
624
// ----------------------------------------------------------------------------------------
625
// wait for end of transmission
626
// returns 1 on success or 0 on timeout
627
u8 I2CBus_WaitForEndOfTransmission(I2C_TypeDef* I2Cx, u32 timeout)
628
{
629
        volatile I2C_Bus_t *pBus = NULL;
630
        u32 time = SetDelay(timeout);
631
 
632
        if(I2Cx == I2C0) pBus = &I2C0_Bus;
633
        if(I2Cx == I2C1) pBus = &I2C1_Bus;
634
        if(pBus == NULL) return(0);
635
        while(pBus->State != I2C_STATE_IDLE)
636
        {
508 holgerb 637
                if(CheckDelay(time))  // Timeout
638
                 {
639
                  return(0);
640
                 }
482 killagreg 641
        }
642
        return(1);
643
}
644
 
645
// ----------------------------------------------------------------------------------------
646
// try to get access to the transfer buffer      within a timeout limit
647
// returs 1 on success and 0 on error/timeout
648
u8 I2CBus_LockBuffer(I2C_TypeDef* I2Cx, u32 timeout)
649
{
650
        volatile I2C_Bus_t *pBus = NULL;       
651
 
652
        if(I2Cx == I2C0) pBus = &I2C0_Bus;
653
        if(I2Cx == I2C1) pBus = &I2C1_Bus;
654
        if(pBus == NULL) return(0);
655
 
656
        if(I2CBus_WaitForEndOfTransmission(I2Cx, timeout))
657
        {
658
                pBus->State = I2C_STATE_BUFFBUSY;
659
                pBus->Error = I2C_ERROR_UNKNOWN;
660
                return(1);
661
        }
662
        else return(0);
663
}
664
// ----------------------------------------------------------------------------------------
665
// initate an i2c transmission
666
// before that function is called, the application has to call I2CBus_LockBuffer and has to fill the Buffer with data to be send
667
u8 I2CBus_Transmission(I2C_TypeDef* I2Cx, u8 SlaveAddr, u8* pTxData, u8 TxBytes, I2C_pRxHandler_t pRxHandler, u8 RxBytes)
668
{
669
        u8 retval = 0;
670
 
671
        volatile I2C_Bus_t *pBus = NULL;       
672
 
673
        if(I2Cx == I2C0) pBus = &I2C0_Bus;
674
        if(I2Cx == I2C1) pBus = &I2C1_Bus;
675
        if(pBus == NULL) return(0);
676
 
677
 
678
        if(pBus->State == I2C_STATE_BUFFBUSY)  // check for locked buffer
679
        {
680
                if((RxBytes > I2C_BUFFER_LEN) || (TxBytes > I2C_BUFFER_LEN))
681
                {
682
                        pBus->State = I2C_STATE_IDLE;
683
                        return(retval);
684
                }      
685
                pBus->RxBufferSize = RxBytes;
686
                pBus->TxBufferSize = TxBytes;
687
                // set direction to master transmitter
688
                if( (pBus->TxBufferSize > 0) && (pBus->TxBufferSize < I2C_BUFFER_LEN) )
689
                {
690
                        pBus->Direction = I2C_MODE_TRANSMITTER;
691
                        // copy data to send from source to tansfer buffer
692
                        if(pTxData) memcpy(pBus->pData, pTxData, pBus->TxBufferSize);
693
                }
694
                else if (( pBus->RxBufferSize > 0 ) && (pBus->RxBufferSize < I2C_BUFFER_LEN) )
695
                {
696
                        pBus->Direction = I2C_MODE_RECEIVER;
697
                }
698
                else // nothing to send or receive
699
                {
700
                        pBus->State = I2C_STATE_IDLE;
701
                        pBus->Error = I2C_ERROR_NONE;
702
                        pBus->TxBufferSize = 0;
703
                        pBus->RxBufferSize = 0;
704
                        return(retval);
705
                }
706
                // update slave address and rx data handler     function pointer
707
                pBus->SlaveAddr = SlaveAddr;
708
                pBus->pRxHandler = pRxHandler;
709
                // test on busy flag and clear it
710
                I2C_ClearFlag(I2Cx, I2C_FLAG_BUSY);
711
                // enable I2C IRQ
712
                VIC_ITCmd(pBus->VIC_Source, ENABLE);
713
                // initiate start condition on the bus
714
                I2C_GenerateStart(I2Cx, ENABLE);
715
                retval = 1;
716
         }
717
         return(retval);
718
}