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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      adc_synth.c
4
//
5
//      ADC driver for Synthetic ADC
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2009 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):    Simon Kallweit <simon.kallweit@intefo.ch>
43
// Contributors:
44
// Date:         2009-02-27
45
// Purpose:
46
// Description:
47
//
48
//####DESCRIPTIONEND####
49
//
50
//==========================================================================
51
 
52
#include <pkgconf/kernel.h>
53
#include <pkgconf/devs_adc_synth.h>
54
 
55
#include <cyg/infra/cyg_type.h>
56
#include <cyg/infra/cyg_ass.h>
57
#include <cyg/io/adc.h>
58
#include <cyg/hal/hal_arch.h>
59
#include <cyg/hal/hal_io.h>
60
#include <cyg/hal/hal_intr.h>
61
#include <cyg/hal/drv_api.h>
62
 
63
//-----------------------------------------------------------------------------
64
// Diagnostic support
65
// Switch the #if to 1 to generate some diagnostic messages.
66
 
67
#if 0
68
#include <cyg/infra/diag.h>
69
#define adc_diag( __fmt, ... ) diag_printf("ADC: %30s[%4d]: " __fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__ );
70
#else
71
#define adc_diag( __fmt, ... ) 
72
#endif
73
 
74
#define NUM_CHANNELS    16
75
 
76
#define MODE_CONST      0
77
#define MODE_RANDOM     1
78
#define MODE_FILE       2
79
 
80
#define SAMPLE_BITS     ((1 << CYGNUM_DEVS_ADC_SYNTH_SAMPLE_SIZE) - 1)
81
 
82
//-----------------------------------------------------------------------------
83
// Synthetic ADC channel
84
 
85
typedef struct synth_adc_channel_info {
86
    cyg_uint32 mode;            // Channel mode
87
    cyg_uint32 const_value;     // Const sample value
88
    char *filename;             // Sampling data filename
89
 
90
    int fd;                     // File descriptor of sample file
91
    cyg_uint32 num_samples;     // Number of samples in the file
92
    cyg_adc_sample_t *base;     // Base address of mapped sample file
93
    cyg_adc_sample_t *sample;   // Current sample
94
 
95
    cyg_adc_sample_t (*get_sample)(cyg_adc_channel *chan);
96
} synth_adc_channel_info;
97
 
98
//-----------------------------------------------------------------------------
99
// Synthetic ADC device
100
 
101
typedef struct synth_adc_info {
102
    synth_adc_channel_info  *chan_info;     // Channel infos
103
    cyg_adc_channel *chan[NUM_CHANNELS];    // Channel references
104
    cyg_uint32 chan_mask;                   // Active channels
105
    cyg_handle_t alarm_handle;              // Alarm handle
106
    cyg_alarm alarm_data;                   // Alarm data
107
    cyg_tick_count_t alarm_interval;        // Alarm interval in ticks
108
    cyg_uint32 alarm_samples;               // Number of samples per tick
109
} synth_adc_info;
110
 
111
//-----------------------------------------------------------------------------
112
// API function call forward references
113
 
114
static bool synth_adc_init(struct cyg_devtab_entry *tab);
115
static Cyg_ErrNo synth_adc_lookup(struct cyg_devtab_entry **tab,
116
                                  struct cyg_devtab_entry *sub_tab,
117
                                  const char *name);
118
 
119
static void synth_adc_enable(cyg_adc_channel *chan);
120
static void synth_adc_disable(cyg_adc_channel *chan);
121
static void synth_adc_set_rate(cyg_adc_channel *chan, cyg_uint32 rate);
122
 
123
static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data);
124
 
125
static cyg_adc_sample_t synth_adc_get_sample_const(cyg_adc_channel *chan);
126
static cyg_adc_sample_t synth_adc_get_sample_random(cyg_adc_channel *chan);
127
static cyg_adc_sample_t synth_adc_get_sample_file(cyg_adc_channel *chan);
128
 
129
static cyg_uint32 rand(void);
130
 
131
CYG_ADC_FUNCTIONS(synth_adc_funs,
132
                  synth_adc_enable,
133
                  synth_adc_disable,
134
                  synth_adc_set_rate);
135
 
136
//-----------------------------------------------------------------------------
137
// Synthetic ADC channel info macro
138
 
139
#define SYNTH_ADC_CHANNEL_INFO(_chan_)                                      \
140
{                                                                           \
141
    .mode           = CYGNUM_DEVS_ADC_SYNTH_CHANNEL##_chan_##_MODE,         \
142
    .const_value    = CYGNUM_DEVS_ADC_SYNTH_CHANNEL##_chan_##_CONST_VALUE,  \
143
    .filename       = CYGDAT_DEVS_ADC_SYNTH_CHANNEL##_chan_##_FILENAME,     \
144
}
145
 
146
//-----------------------------------------------------------------------------
147
// Synthetic ADC channel instance macro
148
 
149
#define SYNTH_ADC_CHANNEL(_chan_)                                           \
150
CYG_ADC_CHANNEL(                                                            \
151
    synth_adc_channel##_chan_,                                              \
152
    _chan_,                                                                 \
153
    CYGNUM_DEVS_ADC_SYNTH_CHANNEL##_chan_##_BUFSIZE,                        \
154
    &synth_adc_device                                                       \
155
);                                                                          \
156
DEVTAB_ENTRY(                                                               \
157
    synth_adc_channel##_chan_##_device,                                     \
158
    CYGDAT_DEVS_ADC_SYNTH_CHANNEL##_chan_##_NAME,                           \
159
    0,                                                                      \
160
    &cyg_io_adc_devio,                                                      \
161
    synth_adc_init,                                                         \
162
    synth_adc_lookup,                                                       \
163
    &synth_adc_channel##_chan_                                              \
164
);
165
 
166
//-----------------------------------------------------------------------------
167
// Synthetic ADC device instance
168
 
169
static synth_adc_channel_info synth_adc_channel_infos[NUM_CHANNELS] = {
170
    SYNTH_ADC_CHANNEL_INFO(0),
171
    SYNTH_ADC_CHANNEL_INFO(1),
172
    SYNTH_ADC_CHANNEL_INFO(2),
173
    SYNTH_ADC_CHANNEL_INFO(3),
174
    SYNTH_ADC_CHANNEL_INFO(4),
175
    SYNTH_ADC_CHANNEL_INFO(5),
176
    SYNTH_ADC_CHANNEL_INFO(6),
177
    SYNTH_ADC_CHANNEL_INFO(7),
178
    SYNTH_ADC_CHANNEL_INFO(8),
179
    SYNTH_ADC_CHANNEL_INFO(9),
180
    SYNTH_ADC_CHANNEL_INFO(10),
181
    SYNTH_ADC_CHANNEL_INFO(11),
182
    SYNTH_ADC_CHANNEL_INFO(12),
183
    SYNTH_ADC_CHANNEL_INFO(13),
184
    SYNTH_ADC_CHANNEL_INFO(14),
185
    SYNTH_ADC_CHANNEL_INFO(15),
186
};
187
 
188
static synth_adc_info synth_adc_info0 = {
189
    .chan_info = synth_adc_channel_infos,
190
};
191
 
192
CYG_ADC_DEVICE(synth_adc_device,
193
               &synth_adc_funs,
194
               &synth_adc_info0,
195
               CYGNUM_DEVS_ADC_SYNTH_DEFAULT_RATE);
196
 
197
SYNTH_ADC_CHANNEL(0)
198
SYNTH_ADC_CHANNEL(1)
199
SYNTH_ADC_CHANNEL(2)
200
SYNTH_ADC_CHANNEL(3)
201
SYNTH_ADC_CHANNEL(4)
202
SYNTH_ADC_CHANNEL(5)
203
SYNTH_ADC_CHANNEL(6)
204
SYNTH_ADC_CHANNEL(7)
205
SYNTH_ADC_CHANNEL(8)
206
SYNTH_ADC_CHANNEL(9)
207
SYNTH_ADC_CHANNEL(10)
208
SYNTH_ADC_CHANNEL(11)
209
SYNTH_ADC_CHANNEL(12)
210
SYNTH_ADC_CHANNEL(13)
211
SYNTH_ADC_CHANNEL(14)
212
SYNTH_ADC_CHANNEL(15)
213
 
214
 
215
//-----------------------------------------------------------------------------
216
// This function is called from the device IO infrastructure to initialize the
217
// device. It should perform any work needed to start up the device, short of
218
// actually starting the generation of samples. This function will be called
219
// for each channel, so if there is initialization that only needs to be done
220
// once, such as creating and interrupt object, then care should be taken to do
221
// this. This function should also call cyg_adc_device_init() to initialize the
222
// generic parts of the driver.
223
 
224
static bool
225
synth_adc_init(struct cyg_devtab_entry *tab)
226
{
227
    static cyg_bool initialized = false;
228
    cyg_adc_channel *chan = (cyg_adc_channel *) tab->priv;
229
    cyg_adc_device *device = chan->device;
230
    synth_adc_info *info = device->dev_priv;
231
    synth_adc_channel_info *chan_info = &info->chan_info[chan->channel];
232
    cyg_handle_t counter;
233
 
234
    adc_diag("Initializing device\n");
235
 
236
    // Initialize channel
237
    info->chan[chan->channel] = chan;
238
    switch (chan_info->mode) {
239
    case MODE_CONST:
240
        chan_info->get_sample = synth_adc_get_sample_const;
241
        break;
242
    case MODE_RANDOM:
243
        chan_info->get_sample = synth_adc_get_sample_random;
244
        break;
245
    case MODE_FILE:
246
        chan_info->get_sample = synth_adc_get_sample_file;
247
        break;
248
    }
249
 
250
    // Set default rate
251
    if (!initialized) {
252
        // Initialize alarm
253
        cyg_clock_to_counter(cyg_real_time_clock(), &counter);
254
        cyg_alarm_create(counter, alarm_handler, (cyg_addrword_t) device,
255
                         &info->alarm_handle, &info->alarm_data);
256
 
257
        synth_adc_set_rate(chan, chan->device->config.rate);
258
        initialized = true;
259
    }
260
 
261
    // Initialize generic parts of ADC device
262
    cyg_adc_device_init(device);
263
 
264
    return true;
265
}
266
 
267
//-----------------------------------------------------------------------------
268
// This function is called when a client looks up or opens a channel. It should
269
// call cyg_adc_channel_init() to initialize the generic part of the channel.
270
// It should also perform any operations needed to start the channel generating
271
// samples.
272
 
273
static Cyg_ErrNo
274
synth_adc_lookup(struct cyg_devtab_entry **tab,
275
                 struct cyg_devtab_entry *sub_tab,
276
                 const char *name)
277
{
278
    cyg_adc_channel *chan = (cyg_adc_channel *) (*tab)->priv;
279
    synth_adc_info *info = chan->device->dev_priv;
280
    synth_adc_channel_info *chan_info = &info->chan_info[chan->channel];
281
 
282
    adc_diag("Opening device\n");
283
 
284
    // When this channel is in file mode, initialize file access
285
    if (chan_info->mode == MODE_FILE) {
286
        struct cyg_hal_sys_new_stat stat;
287
 
288
        // Open the file
289
        chan_info->fd = cyg_hal_sys_open(chan_info->filename,
290
                                         CYG_HAL_SYS_O_RDONLY, 0);
291
        if (chan_info->fd == -ENOENT) {
292
            adc_diag("Cannot open sampling file '%s' for channel '%s'\n",
293
                     chan_info->filename, (*tab)->name);
294
            CYG_FAIL("Cannot open sampling file\n");
295
        }
296
 
297
        // Get file size
298
        if (cyg_hal_sys_newfstat(chan_info->fd, &stat) != 0) {
299
            CYG_FAIL("Cannot stat sampling file\n");
300
        }
301
        chan_info->num_samples = stat.st_size / sizeof(cyg_adc_sample_t);
302
        if (chan_info->num_samples <= 0)
303
            CYG_FAIL("Sampling file too small\n");
304
 
305
        // Memory map
306
        chan_info->base = (cyg_adc_sample_t *) cyg_hal_sys_mmap(
307
            NULL,
308
            chan_info->num_samples * sizeof(cyg_adc_sample_t),
309
            CYG_HAL_SYS_PROT_READ,
310
            CYG_HAL_SYS_MAP_SHARED,
311
            chan_info->fd,
312
            0);
313
        if (chan_info->base == (void *) -1)
314
            CYG_FAIL("Cannot memory map sampling file\n");
315
        chan_info->sample = chan_info->base;
316
 
317
        adc_diag("Mapped to %p\n", chan_info->base);
318
    }
319
 
320
    // Initialize generic parts of the channel
321
    cyg_adc_channel_init(chan);
322
 
323
    // The generic ADC manual says: When a channel is first looked up or 
324
    // opened, then it is automatically enabled and samples start to
325
    // accumulate - so we start the channel now
326
    chan->enabled = true;
327
    synth_adc_enable(chan);
328
 
329
    return ENOERR;
330
}
331
 
332
//-----------------------------------------------------------------------------
333
// This function is called from the generic ADC package to enable the channel
334
// in response to a CYG_IO_SET_CONFIG_ADC_ENABLE config operation. It should
335
// take any steps needed to start the channel generating samples
336
 
337
static void
338
synth_adc_enable(cyg_adc_channel *chan)
339
{
340
    synth_adc_info *info = chan->device->dev_priv;
341
    cyg_bool start;
342
 
343
    adc_diag("Enabling channel\n");
344
 
345
    start = !info->chan_mask;
346
    info->chan_mask |= (1 << chan->channel);
347
 
348
    // Start scanning when first channel was activated
349
    if (start) {
350
        // Enable timer
351
        adc_diag("Starting scanning\n");
352
        cyg_alarm_initialize(info->alarm_handle,
353
                             cyg_current_time() + info->alarm_interval,
354
                             info->alarm_interval);
355
    }
356
}
357
 
358
//-----------------------------------------------------------------------------
359
// This function is called from the generic ADC package to enable the channel
360
// in response to a CYG_IO_SET_CONFIG_ADC_DISABLE config operation. It should
361
// take any steps needed to stop the channel generating samples.
362
 
363
static void
364
synth_adc_disable(cyg_adc_channel *chan)
365
{
366
    synth_adc_info *info = chan->device->dev_priv;
367
 
368
    adc_diag("Disabling channel\n");
369
 
370
    info->chan_mask &= ~(1 << chan->channel);
371
 
372
    // Stop scanning when no channel is active
373
    if (!info->chan_mask) {
374
        // Disable timer
375
        adc_diag("Stopping scanning\n");
376
        cyg_alarm_disable(info->alarm_handle);
377
    }
378
}
379
 
380
//-----------------------------------------------------------------------------
381
// This function is called from the generic ADC package to enable the channel
382
// in response to a CYG_IO_SET_CONFIG_ADC_RATE config operation. It should take
383
// any steps needed to change the sample rate of the channel, or of the entire
384
// device. We use a timer channel to generate the interrupts for sampling the
385
// analog channels
386
 
387
static void
388
synth_adc_set_rate(cyg_adc_channel *chan, cyg_uint32 rate)
389
{
390
    cyg_adc_device *device = chan->device;
391
    synth_adc_info *info = device->dev_priv;
392
    cyg_uint64 interval;
393
 
394
    adc_diag("Setting rate to %d\n", rate);
395
 
396
    interval = 1000000000000LL / rate;
397
    interval /= (CYGNUM_HAL_RTC_NUMERATOR / CYGNUM_HAL_RTC_DENOMINATOR);
398
 
399
    if (interval > 1000) {
400
        info->alarm_interval = interval / 1000;
401
        info->alarm_samples = 1;
402
    } else {
403
        info->alarm_interval = 1;
404
        info->alarm_samples = 1000 / interval;
405
    }
406
 
407
    if (info->chan_mask)
408
        cyg_alarm_initialize(info->alarm_handle,
409
                             cyg_current_time() + info->alarm_interval,
410
                             info->alarm_interval);
411
 
412
    device->config.rate = rate;
413
}
414
 
415
static void
416
alarm_handler(cyg_handle_t alarm, cyg_addrword_t data)
417
{
418
    cyg_adc_device *device = (cyg_adc_device *) data;
419
    synth_adc_info *info = device->dev_priv;
420
    cyg_adc_channel *chan;
421
    synth_adc_channel_info *chan_info;
422
    cyg_uint32 active_mask;
423
    int i, j;
424
 
425
    if (!info->chan_mask)
426
        return;
427
 
428
    active_mask = info->chan_mask;
429
 
430
    for (i = 0; i < NUM_CHANNELS; i++) {
431
        if (active_mask & 0x01) {
432
            chan = info->chan[i];
433
            chan_info = &info->chan_info[chan->channel];
434
            for (j = 0; j < info->alarm_samples; j++)
435
                cyg_adc_receive_sample(chan, chan_info->get_sample(chan));
436
            cyg_adc_wakeup(info->chan[i]);
437
        }
438
        active_mask >>= 1;
439
    }
440
}
441
 
442
static cyg_adc_sample_t
443
synth_adc_get_sample_const(cyg_adc_channel *chan)
444
{
445
    synth_adc_info *info = chan->device->dev_priv;
446
    synth_adc_channel_info *chan_info = &info->chan_info[chan->channel];
447
 
448
    return chan_info->const_value;
449
}
450
 
451
static cyg_adc_sample_t
452
synth_adc_get_sample_random(cyg_adc_channel *chan)
453
{
454
    return rand() & SAMPLE_BITS;
455
}
456
 
457
static cyg_adc_sample_t
458
synth_adc_get_sample_file(cyg_adc_channel *chan)
459
{
460
    synth_adc_info *info = chan->device->dev_priv;
461
    synth_adc_channel_info *chan_info = &info->chan_info[chan->channel];
462
    cyg_adc_sample_t sample;
463
 
464
    sample = *chan_info->sample++;
465
    if (chan_info->sample >= chan_info->base + chan_info->num_samples)
466
        chan_info->sample = chan_info->base;
467
 
468
    return sample;
469
}
470
 
471
//-----------------------------------------------------------------------------
472
// Simple random number generator
473
 
474
static cyg_uint32 rand(void)
475
{
476
    static cyg_uint32 seed;
477
 
478
    seed = (seed * 1103515245) + 12345; // permutate seed
479
 
480
    return seed;
481
}
482
 

powered by: WebSVN 2.1.0

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