OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [adc/] [current/] [src/] [adc.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*==========================================================================
2
//
3
//      adc.c
4
//
5
//      Generic ADC driver layer
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 2008 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later
16
// version.
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21
// for more details.
22
//
23
// You should have received a copy of the GNU General Public License
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26
//
27
// As a special exception, if other files instantiate templates or use
28
// macros or inline functions from this file, or you compile this file
29
// and link it with other works to produce a work based on this file,
30
// this file does not by itself cause the resulting work to be covered by
31
// the GNU General Public License. However the source code for this file
32
// must still be made available in accordance with section (3) of the GNU
33
// General Public License v2.
34
//
35
// This exception does not invalidate any other reasons why a work based
36
// on this file might be covered by the GNU General Public License.
37
// -------------------------------------------
38
// ####ECOSGPLCOPYRIGHTEND####
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    nickg
43
// Date:         2008-03-31
44
// Description:  Implements generic layer of ADC drivers.
45
//
46
//####DESCRIPTIONEND####
47
//
48
//========================================================================*/
49
 
50
#include <cyg/io/adc.h>
51
 
52
//==========================================================================
53
// Diagnostic support
54
//
55
// Switch the #if to 1 to generate some diagnostic messages.
56
 
57
#if 0
58
 
59
#include <cyg/infra/diag.h>
60
 
61
#define adc_diag( __fmt, ... ) diag_printf("ADC: %30s[%4d]: " __fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__ );
62
#define adc_dump_buf( __buf, __size )  diag_dump_buf( __buf, __size )
63
#else
64
#define adc_diag( __fmt, ... ) 
65
#define adc_dump_buf( __buf, __size )
66
#endif
67
 
68
//==========================================================================
69
// Main device table entry functions
70
 
71
static Cyg_ErrNo adc_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len);
72
static Cyg_ErrNo adc_read(cyg_io_handle_t handle, void *buf, cyg_uint32 *len);
73
static cyg_bool adc_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);
74
static Cyg_ErrNo adc_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len);
75
static Cyg_ErrNo adc_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len);
76
 
77
DEVIO_TABLE(cyg_io_adc_devio,
78
            adc_write,
79
            adc_read,
80
            adc_select,
81
            adc_get_config,
82
            adc_set_config
83
    );
84
 
85
//==========================================================================
86
// Device interface functions
87
 
88
//--------------------------------------------------------------------------
89
// Device write
90
//
91
// Not supported
92
 
93
static Cyg_ErrNo adc_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len)
94
{
95
    adc_diag("write not supported\n");
96
    return -EDEVNOSUPP;
97
}
98
 
99
//--------------------------------------------------------------------------
100
// Device Read
101
//
102
// Returns a whole number of samples from a channel
103
 
104
static Cyg_ErrNo adc_read(cyg_io_handle_t handle, void *abuf, cyg_uint32 *len)
105
{
106
    Cyg_ErrNo res = ENOERR;
107
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
108
    cyg_adc_channel *chan = (cyg_adc_channel *)t->priv;
109
    cyg_adc_device *dev = chan->device;
110
 
111
    cyg_adc_sample_t *buf = (cyg_adc_sample_t *)abuf;
112
    cyg_uint32 size = 0;
113
 
114
    adc_diag("chan %d buf %p len %u\n", chan->channel, abuf, *len);
115
 
116
    // Check that supplied buffer address is aligned to sample size.
117
    if( (((CYG_ADDRESS)buf) & (sizeof(cyg_adc_sample_t)-1)) != 0 )
118
        return -EIO;
119
 
120
    // Check that channel is enabled
121
    if( !chan->enabled )
122
        return -EIO;
123
 
124
    cyg_drv_mutex_lock( &dev->lock );
125
    cyg_drv_dsr_lock();
126
    {
127
        while( (*len-size) >= sizeof(cyg_adc_sample_t) )
128
        {
129
            if( chan->put != chan->get )
130
            {
131
                // A sample is available, transfer it to the buffer.
132
 
133
                int next = chan->get+1;
134
                cyg_drv_isr_lock();
135
                {
136
                    *buf++ = chan->buf[chan->get];
137
                    if( next == chan->len )
138
                        next = 0;
139
                    chan->get = next;
140
                }
141
                cyg_drv_isr_unlock();
142
                size += sizeof(cyg_adc_sample_t);
143
 
144
                adc_diag("chan %d sample %d -> %04x\n", chan->channel, size, buf[-1] );
145
            }
146
            else
147
            {
148
                // If there is no data available, either wait or
149
                // return EAGAIN.
150
 
151
                if( !chan->blocking )
152
                {
153
                    // If non-blocking, return what we have. If
154
                    // nothing, return EAGAIN.
155
                    *len = size;
156
                    if( size == 0 )
157
                        res = -EAGAIN;
158
                    break;
159
                }
160
                // Otherwise, we must wait for data to arrive.
161
 
162
                adc_diag("wait for sample\n");
163
                chan->waiting = true;
164
                if( !cyg_drv_cond_wait( &chan->wait ) )
165
                {
166
                    // Abort the wait, return EINTR
167
                    adc_diag("abort\n");
168
                    *len = size;
169
                    res = -EINTR;
170
                    break;
171
                }
172
 
173
                adc_diag("wake up\n");
174
                // Loop back round to pick up any samples now
175
                // available.
176
            }
177
        }
178
    }
179
    cyg_drv_dsr_unlock();
180
    cyg_drv_mutex_unlock( &dev->lock );
181
 
182
    return res;
183
}
184
 
185
//--------------------------------------------------------------------------
186
// Select support
187
//
188
// If select support is enabled, check for pending samples.
189
 
190
static cyg_bool adc_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
191
{
192
#ifdef CYGPKG_IO_ADC_SELECT_SUPPORT
193
 
194
    cyg_bool res = false;
195
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
196
    cyg_adc_channel *chan = (cyg_adc_channel *)t->priv;
197
    cyg_adc_device *dev = chan->device;
198
 
199
    // Check that channel is enabled. If not, return false.
200
    if( !chan->enabled )
201
        return false;
202
 
203
    // Only read select is supported
204
    if( which == CYG_FREAD )
205
    {
206
        cyg_drv_mutex_lock( &dev->lock );
207
        cyg_drv_dsr_lock();
208
        {
209
            cyg_drv_isr_lock();
210
            if( chan->put == chan->get )
211
            {
212
                // There is no data in the buffer, register the select.
213
 
214
                cyg_selrecord( info, &chan->selinfo );
215
            }
216
            else
217
            {
218
                res = true;
219
            }
220
            cyg_drv_isr_unlock();
221
        }
222
        cyg_drv_dsr_unlock();
223
        cyg_drv_mutex_unlock( &dev->lock );
224
 
225
    }
226
 
227
    return res;
228
 
229
#else
230
 
231
    return true;
232
 
233
#endif
234
}
235
 
236
//--------------------------------------------------------------------------
237
// Get config
238
//
239
// Return various configuration options.
240
 
241
static Cyg_ErrNo adc_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf, cyg_uint32 *len)
242
{
243
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
244
    cyg_adc_channel *chan = (cyg_adc_channel *)t->priv;
245
    cyg_adc_info_t *buf = (cyg_adc_info_t *)xbuf;
246
    Cyg_ErrNo res = ENOERR;
247
 
248
    adc_diag("chan %d\n", chan->channel );
249
    switch( key )
250
    {
251
    case CYG_IO_GET_CONFIG_ADC_RATE:
252
        *buf = chan->device->config;
253
        break;
254
 
255
    case CYG_IO_GET_CONFIG_READ_BLOCKING:
256
        if (*len < sizeof(cyg_uint32))
257
            return -EINVAL;
258
        *(cyg_uint32*)xbuf = (chan->blocking) ? 1 : 0;
259
        break;
260
 
261
 
262
    default:
263
        res = -EINVAL;
264
    }
265
 
266
    return res;
267
}
268
 
269
//--------------------------------------------------------------------------
270
// Set config
271
//
272
// Set configuration options.
273
 
274
static Cyg_ErrNo adc_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *xbuf, cyg_uint32 *len)
275
{
276
 
277
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
278
    cyg_adc_channel *chan = (cyg_adc_channel *)t->priv;
279
    cyg_adc_info_t *buf = (cyg_adc_info_t *)xbuf;
280
    Cyg_ErrNo res = ENOERR;
281
 
282
    adc_diag("chan %d\n", chan->channel );
283
 
284
    switch( key )
285
    {
286
    case CYG_IO_SET_CONFIG_ADC_RATE:
287
        chan->device->config = *buf;
288
        chan->device->funs->set_rate( chan, buf->rate );
289
        break;
290
 
291
    case CYG_IO_SET_CONFIG_ADC_ENABLE:
292
        chan->enabled = true;
293
        chan->device->funs->enable( chan );
294
        break;
295
 
296
    case CYG_IO_SET_CONFIG_ADC_DISABLE:
297
        chan->enabled = false;
298
        chan->device->funs->disable( chan );
299
        break;
300
 
301
    case CYG_IO_SET_CONFIG_ADC_DATA_FLUSH:
302
        cyg_drv_isr_lock();
303
        chan->put = 0;
304
        chan->get = 0;
305
        cyg_drv_isr_unlock();
306
        break;
307
 
308
    case CYG_IO_SET_CONFIG_READ_BLOCKING:
309
        if (*len < sizeof(cyg_uint32))
310
            return -EINVAL;
311
 
312
        chan->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
313
        break;
314
 
315
    default:
316
        res = -EINVAL;
317
    }
318
 
319
    return res;
320
}
321
 
322
//==========================================================================
323
// Callbacks from hardware driver to generic layer
324
 
325
//--------------------------------------------------------------------------
326
// Initialize generic device structure
327
 
328
__externC void cyg_adc_device_init( cyg_adc_device *device )
329
{
330
    if( device->init )
331
        return;
332
 
333
    adc_diag("\n");
334
 
335
    device->init = true;
336
    cyg_drv_mutex_init( &device->lock );
337
}
338
 
339
//--------------------------------------------------------------------------
340
// Initialize generic channel structure
341
 
342
__externC void cyg_adc_channel_init(cyg_adc_channel *chan)
343
{
344
    if( chan->init )
345
        return;
346
 
347
    adc_diag("chan %d\n", chan->channel );
348
 
349
    chan->init = true;
350
    cyg_drv_cond_init( &chan->wait, &chan->device->lock );
351
    chan->enabled = false;
352
    chan->waiting = false;
353
    chan->wakeup = false;
354
    chan->blocking = true;
355
    chan->overflow = 0;
356
 
357
#ifdef CYGPKG_IO_ADC_SELECT_SUPPORT
358
        cyg_selinit( &chan->selinfo );
359
#endif        
360
 
361
}
362
 
363
//--------------------------------------------------------------------------
364
// Add a new sample to the buffer
365
//
366
// This function is called from the ISR to store a sample in the
367
// buffer.
368
 
369
__externC cyg_uint32 cyg_adc_receive_sample(cyg_adc_channel *chan, cyg_adc_sample_t sample)
370
{
371
    cyg_uint32 res = 0;
372
    int next = chan->put+1;
373
 
374
    adc_diag("chan %d sample %04x\n", chan->channel, sample );
375
 
376
    // Ignore this sample if the channel is not enabled.
377
    if( !chan->enabled )
378
        return 0;
379
 
380
    if( next == chan->len )
381
        next = 0;
382
 
383
    if( next == chan->get )
384
    {
385
        // The buffer is full. Record an overflow and arrange to
386
        // replace the oldest sample with the new one.
387
 
388
        adc_diag("chan %d overflow\n", chan->channel);
389
        chan->overflow++;
390
 
391
        chan->get++;
392
        if( chan->get == chan->len )
393
            chan->get = 0;
394
    }
395
 
396
    // If this is the first sample into the buffer, wake any waiting
397
    // selectors. Also do this if there are any threads waiting for
398
    // data.
399
    if( chan->put == chan->get || chan->waiting )
400
        res |= CYG_ISR_CALL_DSR, chan->wakeup = true;
401
 
402
    // Store the new sample
403
    chan->buf[chan->put] = sample;
404
    chan->put = next;
405
 
406
    return res;
407
}
408
 
409
//--------------------------------------------------------------------------
410
// Wakeup a channel
411
//
412
// This function is called from the DSR if the channel wakeup field is
413
// set. It satisfies any select operations or any waiting readers.
414
 
415
__externC void cyg_adc_wakeup(cyg_adc_channel *chan )
416
{
417
    adc_diag("chan %d\n", chan->channel );
418
 
419
#ifdef CYGPKG_IO_ADC_SELECT_SUPPORT
420
    cyg_selwakeup( &chan->selinfo );
421
#endif
422
 
423
    chan->waiting = false;
424
    cyg_drv_cond_signal( &chan->wait );
425
 
426
    chan->wakeup = false;
427
}
428
 
429
//==========================================================================
430
// End of adc.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.