summaryrefslogtreecommitdiffhomepage
path: root/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBFIFO/src/usbFifoFT245RL.c
blob: 8ba0d9c50e121f8cff8d08d4932c3f6da2eb459b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/**************************************************************************//**
\file  usbFifoFT245RL.c

\brief Implementation of FT245RL driver.

\author
    Atmel Corporation: http://www.atmel.com \n
    Support email: avr@atmel.com

  Copyright (c) 2008-2011, Atmel Corporation. All rights reserved.
  Licensed under Atmel's Limited License Agreement (BitCloudTM).

\internal
  History:
    12.07.11 A. Khromykh - Created
*******************************************************************************/
/******************************************************************************
                   Includes section
******************************************************************************/
#include <usbFifoVirtualUsart.h>
#include <usart.h>
#include <atomic.h>
#include <irq.h>

/******************************************************************************
                   Define(s) section
******************************************************************************/
#if defined(ATMEGA128RFA1)
// data port
#define USB_DATA_PORT   PORTB
#define USB_DATA_DDR    DDRB
#define USB_DATA_PIN    PINB

#elif defined(ATMEGA1281) || defined(ATMEGA2561)
// data port
#define USB_DATA_PORT   PORTA
#define USB_DATA_DDR    DDRA
#define USB_DATA_PIN    PINA

#endif

#define HANDLERS_GET(A, I) memcpy_P(A, &usbfifoHandlers[I], sizeof(UsbfifoTask_t))

/******************************************************************************
                   Types section
******************************************************************************/
typedef volatile uint8_t UsbfifoTaskBitMask_t;
typedef void (* UsbfifoTask_t)(void);

// USB FIFO task IDs.
typedef enum
{
  USB_FIFO_TASK_RX,
  USB_FIFO_TASK_TX,
  USB_FIFO_TASKS_NUMBER
} UsbfifoTaskId_t;

/******************************************************************************
                   Prototypes section
******************************************************************************/
static void usbfifoRxBufferFiller(void);
static void usbfifoTxBufferCleaner(void);
static void usbfifoPostTask(UsbfifoTaskId_t taskId);
static void usbfifoTxComplete(void);
static void usbfifoRxComplete(void);

/******************************************************************************
                   External global variables section
******************************************************************************/
// pointer to application uart descriptor
extern HAL_UsartDescriptor_t *usbfifoPointDescrip;

/******************************************************************************
                   Global variables section
******************************************************************************/
static volatile UsbfifoTaskBitMask_t usbfifoTaskBitMask = 0; // USB FIFO tasks' bit mask.
static const UsbfifoTask_t PROGMEM_DECLARE(usbfifoHandlers[USB_FIFO_TASKS_NUMBER]) =
{
  usbfifoRxComplete,
  usbfifoTxComplete
}; // List Of possible USB FIFO tasks.

/******************************************************************************
                   Implementations section
******************************************************************************/
/**************************************************************************//**
\brief Startup initialization.
******************************************************************************/
void usbfifoInit(void)
{
  // init decoder input pins
  GPIO_PC6_make_out();
  GPIO_PC7_make_out();
  // set pins to zero to select usb FIFO
  GPIO_PC6_clr();
  GPIO_PC7_clr();

  // setup default value
  GPIO_RD_set();
  GPIO_WR_set();
  // init R\W pins
  GPIO_RD_make_out();
  GPIO_WR_make_out();

  // register RXF interrupt
  HAL_RegisterIrq(IRQ_7, IRQ_LOW_LEVEL, usbfifoRxBufferFiller);
  // register TXE interrupt
  HAL_RegisterIrq(IRQ_6, IRQ_LOW_LEVEL, usbfifoTxBufferCleaner);

  USB_DATA_DDR = 0;
}

/**************************************************************************//**
\brief Clear startup initialization parameters
******************************************************************************/
void usbfifoUnInit(void)
{
  GPIO_PC6_make_in();
  GPIO_PC7_make_in();

  GPIO_RD_make_in();
  GPIO_WR_make_in();

  HAL_DisableIrq(IRQ_7);
  HAL_UnregisterIrq(IRQ_7);

  HAL_DisableIrq(IRQ_6);
  HAL_UnregisterIrq(IRQ_6);
}

/**************************************************************************//**
\brief Puts the byte received to the cyclic buffer.
******************************************************************************/
static void usbfifoRxBufferFiller(void)
{
  uint16_t           old;
  uint16_t           poW;
  uint16_t           poR;
  uint8_t           *buffer;
  HalUsartService_t *control;

  if (!usbfifoPointDescrip)
  { // unregistered intrrupt is occurred
    HAL_DisableIrq(IRQ_7);
    return;
  }

  control = &usbfifoPointDescrip->service;
  poW = control->rxPointOfWrite;
  poR = control->rxPointOfRead;
  buffer = usbfifoPointDescrip->rxBuffer;

  if (!buffer)
  {
    HAL_DisableIrq(IRQ_7);
    return;
  }

  old = poW;

  if (++poW == usbfifoPointDescrip->rxBufferLength)
    poW = 0;

  if (poW == poR)
  { // Buffer full.
    HAL_DisableIrq(IRQ_7);
    return;
  } // Buffer full.

  control->rxPointOfWrite = poW;
  GPIO_RD_clr();
  NOP;
  buffer[old] = USB_DATA_PIN;
  GPIO_RD_set();
  control->rxBytesInBuffer++;
  usbfifoPostTask(USB_FIFO_TASK_RX);
}

/**************************************************************************//**
\brief Reads byte from tx buffer and sends it to fifo.
******************************************************************************/
static void usbfifoTxBufferCleaner(void)
{
  HalUsartService_t *control;
  uint16_t           poW;
  uint16_t           poR;

  if (!usbfifoPointDescrip)
  { // unregistered intrrupt is occurred
    HAL_DisableIrq(IRQ_6);
    return;
  }

  control = &usbfifoPointDescrip->service;
  poW = control->txPointOfWrite;
  poR = control->txPointOfRead;

  if (poW != poR)
  {
    // set port as output
    USB_DATA_DDR = 0xFF;
    NOP;
    USB_DATA_PORT = usbfifoPointDescrip->txBuffer[poR++];
    GPIO_WR_clr();
    GPIO_WR_set();
    USB_DATA_DDR = 0;

    if (poR == usbfifoPointDescrip->txBufferLength)
      poR = 0;

    control->txPointOfRead = poR;
  }
  else
  { // tx buffer is empty
    HAL_DisableIrq(IRQ_6);
    usbfifoPostTask(USB_FIFO_TASK_TX);
  }
}

/**************************************************************************//**
\brief Transmitting complete handler
******************************************************************************/
static void usbfifoTxComplete(void)
{
  if (NULL == usbfifoPointDescrip)
    return;

  if (0 == usbfifoPointDescrip->txBufferLength)
    usbfifoPointDescrip->txBuffer = NULL; // nulling pointer for callback mode

  if (usbfifoPointDescrip->txCallback)
    usbfifoPointDescrip->txCallback();
}

/**************************************************************************//**
\brief Byte is received handler
******************************************************************************/
static void usbfifoRxComplete(void)
{
  HalUsartService_t *control;
  uint16_t           number;

  if (NULL == usbfifoPointDescrip)
    return;

  control = &usbfifoPointDescrip->service;
  ATOMIC_SECTION_ENTER
    number = control->rxBytesInBuffer;
  ATOMIC_SECTION_LEAVE

  if (number)
    if (NULL != usbfifoPointDescrip->rxCallback)
      usbfifoPointDescrip->rxCallback(number);
}

/**************************************************************************//**
\brief  USB FIFO driver task handler.
******************************************************************************/
void usbfifoHandler(void)
{
  UsbfifoTask_t         handler;
  uint8_t               mask = 1;
  UsbfifoTaskId_t       index = 0;

  for ( ; index < USB_FIFO_TASKS_NUMBER; index++, mask <<= 1)
  {
    if (usbfifoTaskBitMask & mask)
    {
      ATOMIC_SECTION_ENTER
      usbfifoTaskBitMask ^= mask;
      ATOMIC_SECTION_LEAVE
      HANDLERS_GET(&handler, index);
      handler();
    }
  }
}

/**************************************************************************//**
\brief Posts specific USART task.

\param[in]
  taskId - unique identifier of the task to be posted.
******************************************************************************/
static void usbfifoPostTask(UsbfifoTaskId_t taskId)
{
  usbfifoTaskBitMask |= (UsbfifoTaskBitMask_t)1 << taskId;
  halPostTask4(HAL_EXT_HANDLER);
}

// eof usbFifoFT245RL.c