source: multiio/rtd6425/rtd6425.c @ d35032f

Last change on this file since d35032f was d35032f, checked in by Joel Sherrill <joel.sherrill@…>, on 10/05/11 at 18:09:53

2011-10-05 Joel Sherrill <joel.sherrill@…>

  • .cvsignore, ChangeLog?, Makefile, multiio_rtd6425.c, rtd6425.c, rtd6425.h: New files.
  • Property mode set to 100644
File size: 24.1 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2011.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 *
9 *  $Id$
10 */
11
12#define LIB_DEFINED
13
14/* #define DEBUG 1 */
15
16#include <bsp.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include "rtd6425.h"
20#include <bsp/irq.h>
21
22/* RTEMS Ids for Wait Queues */
23rtems_id     rtd6425_dio_wq;
24unsigned int rtd6425_dio_missed_interrupts;
25
26
27typedef struct {
28  uint16_t  irq;
29  uint8_t   irqmask;
30  uint8_t   previous;
31} rtd6425_control_t;
32
33rtd6425_control_t rtd6425_info[2];
34
35/*
36 *  Limits on number of buffered discrete input interrupts in
37 *  the message queue.
38 */
39#define MAXIMUM_BUFFERED_DISCRETE_INTERRUPTS 1024
40
41typedef struct {
42  struct timespec timestamp;
43  int             pin;
44} rtd6425_din_message_t;
45
46typedef struct {
47  uint8_t  p0_direction; /* each bit 1 == output, 0 == input */
48  bool     p1_direction; /* true when all output */
49  uint8_t  p2_direction; /* each bit 1 == output, 0 == input */
50  bool     p3_direction; /* true when all output */
51  uint16_t control_reg;  /* value to program the conrtol register */
52  uint16_t irq_reg;      /* value to program the irq register */
53} rtd6425_config_t;
54
55rtd6425_config_t rtd6425_configuration = {
56  0x00,   /* p0_direction - each bit 1 == output, 0 == input */
57  false,  /* p1_direction - true when all output */
58  0x00,   /* p2_direction - each bit 1 == output, 0 == input */
59  false,  /* p3_direction - true when all output */
60  0x00,
61  0x00
62};
63
64typedef enum  {
65  RTD6425_ADC_RANGE_NEG_5_TO_5   = 0x0,
66  RTD6425_ADC_RANGE_NEG_10_TO_10 = 0x1,
67  RTD6425_ADC_RANGE_0_TO_10      = 0x2
68} rtd6425_adc_range_t;
69
70typedef enum  {
71  RTD6425_ADC_GAIN_NONE = 0x0,
72  RTD6425_ADC_GAIN_X1   = 0x1,
73  RTD6425_ADC_GAIN_X2   = 0x2,
74  RTD6425_ADC_GAIN_X4   = 0x4,
75  RTD6425_ADC_GAIN_X8   = 0x8,
76} rtd6425_adc_gain_t;
77
78typedef enum {
79  RTD6425_ADC_SINGLE_ENDED = 0,
80  RTD6425_ADC_DIFFERENTIAL = 1
81} rtd6425_adc_se_diff_t;
82
83typedef struct {
84   rtd6425_adc_range_t   range;
85   rtd6425_adc_gain_t    gain;
86   rtd6425_adc_se_diff_t se_diff;
87} rtd6425_adc_config_t;
88
89#define RTD6425_ADC_DEFAULT_CONFIGURATION \
90  { RTD6425_ADC_RANGE_NEG_10_TO_10, RTD6425_ADC_GAIN_NONE, RTD6425_ADC_SINGLE_ENDED }
91
92rtd6425_adc_config_t rtd6425_adc_configuration[ RTD6425_ADCs ] = {
93  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 00 */
94  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 01 */
95  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 02 */
96  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 03 */
97  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 04 */
98  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 05 */
99  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 06 */
100  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 07 */
101  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 08 */
102  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 09 */
103  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 10 */
104  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 11 */
105  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 12 */
106  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 13 */
107  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 14 */
108  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 15 */
109  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 16 */
110  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 17 */
111  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 18 */
112  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 19 */
113  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 20 */
114  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 21 */
115  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 22 */
116  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 23 */
117  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 24 */
118  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 25 */
119  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 26 */
120  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 27 */
121  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 28 */
122  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 29 */
123  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 30 */
124  RTD6425_ADC_DEFAULT_CONFIGURATION,  /* ADC 31 */
125};
126
127bool rtd6425_is_writable( int pin )
128{
129  int      port;
130  int      position;
131  uint8_t  mask;
132
133  port  = pin / 8;
134
135  if ( port == 1 ) {
136    if ( rtd6425_configuration.p1_direction == true )
137      return false;
138    return true;
139  }
140
141  if ( port == 3 ) {
142    if ( rtd6425_configuration.p3_direction == true )
143      return false;
144    return true;
145  }
146
147  if ( port == 0 )
148    mask = rtd6425_configuration.p0_direction;
149  else
150    mask = rtd6425_configuration.p2_direction;
151
152  position = pin / 8;
153  if ( (mask & (1 << position)) != 0 )
154    return true;
155
156  return false;
157}
158
159#if 1
160  #define DEBUG_PRINT(...) printk( __VA_ARGS__ )
161#else
162  #define DEBUG_PRINT(...)
163#endif
164
165#define rtd6425_outport_byte( _port, _value ) \
166  do { \
167    DEBUG_PRINT( "OUTB 0x%04x to 0x%04x\n", _value, _port ); \
168    outport_byte( _port, _value ); \
169  } while (0)
170
171#define rtd6425_inport_byte( _port, _value ) \
172  do { \
173    inport_byte( _port, _value ); \
174    DEBUG_PRINT( "INB 0x%04x from 0x%04x\n", _value, _port ); \
175  } while (0)
176
177#define rtd6425_outport_word( _port, _value ) \
178  do { \
179    DEBUG_PRINT( "OUTW 0x%04x to 0x%04x\n", _value, _port ); \
180    outport_word( _port, _value ); \
181  } while (0)
182
183#define rtd6425_inport_word( _port, _value ) \
184  do { \
185    inport_word( _port, _value ); \
186    DEBUG_PRINT( "INW 0x%04x from 0x%04x\n", _value, _port ); \
187  } while (0)
188
189uint16_t rtd6425_base;
190
191#define DIO_SELECT_CLEAR      0
192#define DIO_SELECT_DIRECTION  1
193#define DIO_SELECT_MASK       2
194#define DIO_SELECT_COMPARE    3
195
196void rtd6425_DIO_select_register(uint8_t port, uint8_t reg)
197{
198  uint8_t value;
199
200  rtd6425_inport_byte(
201    rtd6425_base  + RTD6425_MODE_5812 + (port * 0x400),
202    value
203  );
204
205DEBUG_PRINT("select_reg1: port: %d, reg: %d, val: 0x%02x\n", port, reg, value);
206
207  value &= 0xFC;
208  value |= reg;
209 
210  rtd6425_outport_byte( rtd6425_base + RTD6425_MODE_5812 + (port * 0x400), value);
211
212  rtd6425_inport_byte(
213    rtd6425_base  + RTD6425_MODE_5812 + (port * 0x400),
214    value
215  );
216
217DEBUG_PRINT("select_reg2: port: %d, reg: %d, val: 0x%02x\n", port, reg, value);
218}
219
220void rtd6425_write_dio_status(uint8_t chip, uint8_t mask, uint8_t new)
221{
222  uint8_t value;
223
224  rtd6425_inport_byte(
225    rtd6425_base  + RTD6425_MODE_5812 + (chip * 0x400),
226    value
227  );
228
229  DEBUG_PRINT("write_dio_status1: chip: %d, mask: %d, val: 0x%02x\n", chip, mask, value);
230
231
232  value &= 0xFC;
233  value &= ~mask;
234  value |= new;
235
236  rtd6425_outport_byte( rtd6425_base + RTD6425_MODE_5812 + (chip * 0x400), value);
237
238  rtd6425_inport_byte(
239    rtd6425_base  + RTD6425_MODE_5812 + (chip * 0x400),
240    value
241  );
242
243  DEBUG_PRINT("write_dio_status2: chip: %d, mask: %d, val: 0x%02x\n", chip, mask, value);
244
245}
246
247uint8_t rtd6425_read_dio_status( uint8_t chip )
248{
249  uint8_t value;
250
251  rtd6425_inport_byte(
252    rtd6425_base  + RTD6425_MODE_5812 + (chip * 0x400),
253    value
254  );
255
256  DEBUG_PRINT("read_dio_status: chip: %d val: 0x%02x\n", chip, value);
257
258  return value;
259}
260
261void rtd6425_din_queue_create(
262  rtems_name  name,
263  rtems_id   *id
264)
265{
266  rtems_status_code rc;
267
268  rc = rtems_message_queue_create(
269    name,
270    MAXIMUM_BUFFERED_DISCRETE_INTERRUPTS,
271    sizeof(rtd6425_din_message_t),
272    RTEMS_DEFAULT_ATTRIBUTES,
273    id
274  );
275  if ( rc == RTEMS_SUCCESSFUL )
276    return;
277
278  DEBUG_PRINT( "Unable to create RTD6425 DIN IRQ Message Queue\n" );
279  exit(1);
280}
281
282void rtd6425_initialize(
283  unsigned short base_port,
284  unsigned short irq0,
285  unsigned short irq1
286)
287{
288  uint16_t ignored;
289  uint16_t value;
290  int      i;
291
292  /* Create RTEMS Objects */
293  rtd6425_din_queue_create(
294    rtems_build_name( 'd', 'i', 'o', ' ' ),
295    &rtd6425_dio_wq
296  );
297  rtd6425_dio_missed_interrupts = 0;
298
299printf( "RTD6426 Init( 0x%04x, 0x%04x, 0x%04x )\n", base_port, rtd6425_info[0].irq, rtd6425_info[1].irq );
300  rtd6425_base = base_port;
301  rtd6425_info[0].irq = irq0;
302  rtd6425_info[1].irq  = irq1;
303
304  /*
305   * Validate ADC Table.
306   */
307  for( i=0; i<RTD6425_ADCs; i=i+2 ) {
308    if ( rtd6425_adc_configuration[i].se_diff !=
309         rtd6425_adc_configuration[i].se_diff ) {
310      DEBUG_PRINT("Error==> ADC single ended mismatch\n");
311      exit (0);
312    }
313
314    if ( rtd6425_adc_configuration[i].se_diff == RTD6425_ADC_DIFFERENTIAL ) {
315      if (rtd6425_adc_configuration[i].range !=
316         rtd6425_adc_configuration[i].range ) {
317        DEBUG_PRINT("Error==> ADC range mismatch - Either choose single ended or match the range of the twisted pair\n");
318        exit (0);
319      }
320    }
321  }
322
323  /*
324   *  Reset Board and clear it out
325   */
326  rtd6425_outport_word( rtd6425_base + RTD6425_CLEAR, 0x0001 );
327  rtd6425_inport_word( rtd6425_base + RTD6425_CLEAR, ignored );
328
329  /*
330   *  Clear ADDMADone
331   */
332  rtd6425_outport_word( rtd6425_base + RTD6425_CLEAR, 0x0004 );
333  rtd6425_inport_word( rtd6425_base + RTD6425_CLEAR, ignored );
334
335  /*
336   * Clear Gain Table
337   */
338  rtd6425_outport_word( rtd6425_base + RTD6425_CLEAR, 0x0008 );
339  rtd6425_inport_word( rtd6425_base + RTD6425_CLEAR, ignored );
340
341  /*
342   *  Clear ADC FIFOs
343   */
344  rtd6425_outport_word( rtd6425_base + RTD6425_CLEAR, 0x0002 );
345  rtd6425_inport_word( rtd6425_base + RTD6425_CLEAR, ignored );
346
347  /*
348   *  Clear DIN FIFOs
349   */
350  rtd6425_outport_word( rtd6425_base + RTD6425_CLEAR, 0x0020 );
351  rtd6425_inport_word( rtd6425_base + RTD6425_CLEAR, ignored );
352
353  /*
354   * Program Discrete I/O directions
355   */
356  rtd6425_DIO_select_register( 0, DIO_SELECT_DIRECTION );
357  rtd6425_outport_word(
358    rtd6425_base + RTD6425_PORT_DIR_5812 + (0*0x400),
359    rtd6425_configuration.p0_direction
360  );
361
362  rtd6425_write_dio_status(
363    0,
364    0x04,
365    (rtd6425_configuration.p1_direction) ? 0x04 : 0x00
366  );
367
368  rtd6425_DIO_select_register( 1, DIO_SELECT_DIRECTION );
369  rtd6425_outport_word(
370    rtd6425_base + RTD6425_PORT_DIR_5812 + (1*0x400),
371    rtd6425_configuration.p2_direction
372  );
373
374  rtd6425_write_dio_status(
375    1,
376    0x04,
377    (rtd6425_configuration.p1_direction) ? 0x04 : 0x00
378  );
379DEBUG_PRINT("END: Program discrete I/O directions\n");
380
381  rtd6425_outport_word( rtd6425_base + RTD6425_TRIGGER, 0x00 );
382
383  /*
384   * Set the
385   */
386  //Enable loading channel gain latch
387  rtd6425_configuration.control_reg  &= 0xFFFC;
388  rtd6425_outport_word( rtd6425_base + RTD6425_CONTROL, rtd6425_configuration.control_reg );
389 
390  for( i=0; i<RTD6425_ADCs; i++) {
391  value = (i) |
392          (rtd6425_adc_configuration[i].gain << 5) |
393          (rtd6425_adc_configuration[i].range << 8) |
394          (rtd6425_adc_configuration[i].se_diff << 10);
395
396    rtd6425_outport_word( rtd6425_base + RTD6425_CHANNEL_GAIN, value );
397  }
398DEBUG_PRINT("End ADC setup\n");
399}
400
401void rtd6425_chip_mode_select( uint8_t chip )
402{
403    uint8_t value;
404    uint8_t mode = 0; /* Event Mode */
405
406    /* Clear Bit to set to event mode */
407    rtd6425_inport_byte(
408      rtd6425_base  + RTD6425_MODE_5812 + (chip * 0x400),
409      value
410    );
411    value  &= 0xf7;
412    value |= (mode << 3);
413    rtd6425_outport_byte(
414      rtd6425_base + RTD6425_MODE_5812 + (chip * 0x400),
415      value
416    );
417}
418
419void rtd6425_set_IRQ(uint8_t chip, uint16_t source, uint16_t channel)
420{
421  uint16_t value;
422
423  switch(channel) {
424      case 3:  channel = 1; break;
425      case 5:  channel = 2; break;
426      case 9:  channel = 3; break;
427      case 10: channel = 4; break;
428      case 11: channel = 5; break;
429      case 12: channel = 6; break;
430      case 15: channel = 7; break;
431      default: channel = 0; break;
432  }
433   
434  if (chip == 0)
435    rtd6425_configuration.irq_reg =
436      rtd6425_configuration.irq_reg & 0xff00;
437  else
438    rtd6425_configuration.irq_reg =
439      rtd6425_configuration.irq_reg & 0x00ff;
440
441  value = source | (channel << 5);
442  rtd6425_configuration.irq_reg |= value << (chip*8);
443  rtd6425_outport_word(
444    rtd6425_base + RTD6425_IRQ,
445    rtd6425_configuration.irq_reg
446  );
447}
448
449void rtd6425_enable_interrupt(uint8_t chip, uint8_t enable)
450{
451  uint8_t value;
452
453  rtd6425_info[chip].irqmask  = (enable) ? 0xff : 0;
454  rtd6425_inport_byte(
455    rtd6425_base + (chip * 0x400) + RTD6425_PORT_0_5812,
456    rtd6425_info[chip].previous
457  );
458
459  /* Clear Bit to set to event mode */
460  rtd6425_inport_byte(
461    rtd6425_base  + RTD6425_MODE_5812 + (chip * 0x400),
462    value
463  );
464  value &= 0xef;
465  value |= (enable << 4);
466  rtd6425_outport_byte(
467    rtd6425_base + RTD6425_MODE_5812 + (chip * 0x400),
468    value
469  );
470}
471
472void rtd6425_dio_check_pin_change(
473  uint8_t                 base_bit,
474  uint8_t                 previous,
475  uint8_t                 current,
476  uint8_t                 mask,
477  rtd6425_din_message_t  *din
478)
479{
480  uint8_t            changed;
481  int                pin;
482  int                pin_mask;
483  rtems_status_code  rc;
484
485  /*
486   * Calculate which bits changed that we care about
487   */
488  changed = (previous ^ current) & mask;
489
490  // printk( "check: %d prev=0x%02x curr=0x%02x mask=0x%02x\n",
491  //    base_bit, previous, current, mask );
492
493  for ( pin=0 ; changed != 0 && pin<8 ; pin++ ) {
494    pin_mask = 1 << pin;
495    if ( (changed & pin_mask) == 0 )
496      continue;
497
498    din->pin = base_bit + pin;
499    // printk( "check: %d changed\n", din->pin );
500    rc = rtems_message_queue_send(
501      rtd6425_dio_wq,
502      din,
503      sizeof(rtd6425_din_message_t)
504    );
505    if ( rc != RTEMS_SUCCESSFUL ) {
506      rtd6425_dio_missed_interrupts++;
507      DEBUG_PRINT("<1>Missed DIO interrupt %d\n", rc );
508    }
509    changed &= ~pin_mask;
510  }
511}
512
513void  rtd6425_clear_Irq6425( void )
514{
515    uint16_t value;
516
517    /* ClearIRQ16425 */
518    rtd6425_outport_word( rtd6425_base  + RTD6425_CLEAR, 0x00C0 );
519    rtd6425_inport_word( rtd6425_base  + RTD6425_CLEAR, value );
520}
521
522void  rtd6425_clear_Irq5812(uint8_t chip)
523{
524  uint8_t value;
525
526  rtd6425_DIO_select_register(chip, 0);
527  rtd6425_inport_byte(
528    rtd6425_base  + RTD6425_CLEAR_5812 + (chip * 0x400),
529    value
530  );
531}
532
533rtems_isr rtd6425_dio_handler(void *arg);
534
535rtems_irq_connect_data rtd6425_dio_cd0 = {
536 0, rtd6425_dio_handler, (void *) &rtd6425_dio_cd0, NULL, NULL, NULL, NULL
537};
538rtems_irq_connect_data rtd6425_dio_cd1 = {
539 0, rtd6425_dio_handler, (void *) &rtd6425_dio_cd1, NULL, NULL, NULL, NULL
540};
541
542int rtd6425_enable_dio_interrupt(void)
543{
544     int i;
545     uint8_t mask, status;
546  uint8_t v8;
547DEBUG_PRINT("Start  rtd6425_enable_dio_interrupt\n");
548
549  /* Set IRQ Source Digital IO. */
550  /* XXX - Verify this */
551  rtd6425_set_IRQ(0, 10, rtd6425_info[0].irq );
552  rtd6425_set_IRQ(1, 16, rtd6425_info[1].irq );
553
554  rtd6425_dio_cd0.name = rtd6425_info[0].irq;
555  rtd6425_dio_cd1.name = rtd6425_info[1].irq;
556
557  /* Install handler for each irq */
558  BSP_install_rtems_shared_irq_handler( &rtd6425_dio_cd0 );
559  BSP_install_rtems_shared_irq_handler( &rtd6425_dio_cd1 );
560
561  // insure there won't be any interrupts from preset values on ports 0/1
562  rtd6425_outport_byte(
563    rtd6425_base + RTD6425_PORT_0_5812 + (0 * 0x400) + (1 * 2),
564    0Xff
565  );
566  rtd6425_outport_byte(
567    rtd6425_base + RTD6425_PORT_0_5812 + (1 * 0x400) + (1 * 2),
568    0Xff
569  );
570
571  // set event mode for port interrupt
572  rtd6425_chip_mode_select( 0 );
573  rtd6425_chip_mode_select( 1 );
574
575  // insures that no bits will be masked for interrupts
576  DEBUG_PRINT("Set Mask for chip\n");
577  rtd6425_DIO_select_register(0, 2 );
578  rtd6425_outport_byte(
579    rtd6425_base + RTD6425_PORT_MASK_5812 + (0  * 0x400) ,
580    0x00
581  );
582  rtd6425_DIO_select_register(1, 2 );
583  rtd6425_outport_byte(
584     rtd6425_base + RTD6425_PORT_MASK_5812 + (1  * 0x400) ,
585    0x00
586  );
587
588  DEBUG_PRINT("Turn interrupts on\n");
589  rtd6425_enable_interrupt(0, 1);         // enable interrupt circuit at Port
590  rtd6425_enable_interrupt(1, 1);         // enable interrupt circuit at Port
591 
592  /* ClearIrq5812(PORTSELECT01); */
593  rtd6425_DIO_select_register( 0, 0 );
594  rtd6425_inport_byte( rtd6425_base + (0 * 0x400)  + RTD6425_CLEAR_5812, v8 );
595  rtd6425_DIO_select_register( 1, 0 );
596  rtd6425_inport_byte( rtd6425_base + (1 * 0x400)  + RTD6425_CLEAR_5812, v8 );
597   rtd6425_clear_Irq6425();
598
599  rtd6425_clear_Irq5812(0);
600  rtd6425_clear_Irq5812(1);
601
602 
603  for (i=0; i<2;i++){
604     rtd6425_inport_byte(
605      rtd6425_base + RTD6425_PORT_MASK_5812 + (i  * 0x400),
606      mask
607    );
608     rtd6425_inport_byte(
609      rtd6425_base + RTD6425_STATUS_5812 + (i  * 0x400),
610      status
611    );
612    printk( "chip %d Mask: 0x%x Status: 0x%x IRQ: 0x%x\n",
613      i,mask, status, rtd6425_configuration.irq_reg
614    );
615  }
616
617  DEBUG_PRINT("Return from rtd6425_enable_dio_interrupt\n");
618
619  return 0;
620}
621
622int rtd6425_dio_enab_bit_int(int bit_number, int polarity)
623{
624  int       dio_port;
625  uint8_t   value;
626  uint8_t   mask;
627  uint16_t  io_port;
628  uint8_t   new;
629
630  if ( bit_number > RTD6425_DISCRETE_IO_BITS )
631    return -1;
632
633  dio_port = bit_number / 8;
634  mask     = 1 << (bit_number % 8);
635  new      = ((polarity) ? mask : 0);
636  mask     = ~mask;
637
638  switch ( dio_port ) {
639    case 0: io_port = RTD6425_PORT_0_5812;         break;
640    case 1: io_port = RTD6425_PORT_1_5812;         break;
641    case 2: io_port = RTD6425_PORT_0_5812 + 0x400; break;
642    case 3: io_port = RTD6425_PORT_1_5812 + 0x400; break;
643    default: return -1;
644  }
645
646  rtd6425_DIO_select_register(0, 2 );
647
648  // read the mask register and calculate the field
649  rtd6425_inport_byte(
650    rtd6425_base + RTD6425_PORT_MASK_5812 + (0  * 0x400),
651    value
652  );
653
654DEBUG_PRINT("read interrupt mask 0x%x\n", value);
655  value &= mask;
656  value |= ~mask;
657DEBUG_PRINT("write interrupt mask 0x%x\n", value);
658
659  // write the value to the mask register
660  rtd6425_DIO_select_register(0, 2 );
661  rtd6425_outport_byte(
662    rtd6425_base + RTD6425_PORT_MASK_5812 + (0  * 0x400) ,
663    value
664  );
665
666
667  return 0;
668}
669
670void rtd6425_flush_buffered_ints(void)
671{
672}
673
674int  rtd6425_wait_dac_int_with_timeout(int dac_num, int milliseconds)
675{
676  return 0;
677}
678
679int  rtd6425_wait_dio_int_with_timeout(int milliseconds)
680{
681  return 0;
682}
683
684int  rtd6425_wait_dio_int_with_timestamp(
685  int              milliseconds,
686  struct timespec *timestamp
687)
688{
689  rtems_status_code      rc;
690  rtd6425_din_message_t  din;
691  size_t                 received;
692
693  mio_error_code = MIO_SUCCESS;
694
695  rc = rtems_message_queue_receive(
696    rtd6425_dio_wq,
697    &din,
698    &received,
699    RTEMS_DEFAULT_OPTIONS,
700    RTEMS_MILLISECONDS_TO_TICKS(milliseconds)
701  );
702  if ( rc == RTEMS_UNSATISFIED ) {
703    mio_error_code = MIO_READ_DATA_FAILURE;
704    return -1;
705  }
706
707  if ( rc == RTEMS_TIMEOUT ) {
708    mio_error_code = MIO_TIMEOUT_ERROR;
709    return -1;
710  }
711
712  if ( rc != RTEMS_SUCCESSFUL ) {
713    DEBUG_PRINT( "wait_dio_int_with_timestamp - error %d\n", rc );
714    exit( 0 );
715  }
716
717  if (timestamp)
718    *timestamp = din.timestamp;
719  return din.pin;
720}
721
722int rtd6425_dio_get_missed_interrupts(void)
723{
724  return 0;
725}
726
727float rtd6425_adc_get_channel_voltage(int channel)
728{
729  int16_t  value;
730  float    result = 0;
731
732  rtd6425_outport_word( rtd6425_base + RTD6425_CLEAR, 0x0002 );
733  rtd6425_inport_word( rtd6425_base + RTD6425_CLEAR, value );
734
735  rtd6425_configuration.control_reg  &= 0xFFFC;    //Enable loading channel gain latch
736  rtd6425_outport_word( rtd6425_base + RTD6425_CONTROL, rtd6425_configuration.control_reg );
737 
738  value = (channel) |
739          (rtd6425_adc_configuration[channel].gain << 5) |
740          (rtd6425_adc_configuration[channel].range << 8) |
741          (rtd6425_adc_configuration[channel].se_diff << 10);
742
743  rtd6425_outport_word( rtd6425_base + RTD6425_CHANNEL_GAIN, value );
744
745  /* Start Conversion */
746  rtd6425_inport_word( rtd6425_base +  RTD6425_START_CONVERSION, value );
747 
748  /* Wait on Fifo to not be empty */
749   while ( ( value & 0x1 ) == 0 )
750     rtd6425_inport_word( rtd6425_base +  RTD6425_STATUS, value );
751   
752   rtd6425_inport_word( rtd6425_base +  RTD6425_AD, value );
753   value = value >> 3;
754   printf("ADC Read: 0x%03x\n", value );
755
756   switch( rtd6425_adc_configuration[channel].range ) {
757    case RTD6425_ADC_RANGE_NEG_5_TO_5:
758      result = (( 10.0 / 4095.0) * value);
759      break;
760    case RTD6425_ADC_RANGE_NEG_10_TO_10:
761      result = (( 20.0 / 4095.0) * value);
762      break;
763    case RTD6425_ADC_RANGE_0_TO_10:
764      result = (( 10.0 / 4095.0) * value);
765      break;
766   };
767
768   return result;
769}
770
771int rtd6425_set_dac_voltage(int channel, float voltage)
772{
773  uint16_t  value;
774  float     per_bit;
775  uint16_t  dac_setup;
776  uint16_t  range_select;
777
778  // printf( "Write DAC %d %fV\n", channel, voltage );
779  /*
780   * Read DAC Setup, clean out bits indicating DAC selected
781   */
782  rtd6425_inport_word( rtd6425_base + RTD6425_DA_SETUP, dac_setup );
783  dac_setup &= ~(3 << (channel * 2));
784
785  /*
786   *  Do some magic per range
787   */
788  if ( voltage >= 0.0 && voltage <= 5.0 ) {
789    per_bit      = 5.0 / 4095;
790    value        = (uint16_t) (voltage / per_bit);
791    range_select = RTD6425_DAC_0V_to_5V;
792  } else if ( voltage >= -5.0 && voltage <= 5.0 ) {
793    per_bit      = 10.0 / 4095;
794    value        = (uint16_t) ((voltage + 5.0) / per_bit);
795    range_select = RTD6425_DAC_MINUS_5V_TO_5V;
796  } else if ( voltage >= 0.0 && voltage <= 10.0 ) {
797    per_bit      = 10.0 / 4095;
798    value        = (uint16_t) (voltage / per_bit);
799    range_select = RTD6425_DAC_0V_TO_10V;
800  } else if ( voltage >= -10.0 && voltage <= 10.0 ) {
801    per_bit      = 20.0 / 4095;
802    value        = (uint16_t) ((voltage + 10.0) / per_bit);
803    range_select = RTD6425_DAC_MINUS_10_TO_10V;
804  } else {
805    printf( "Voltage is out of range %f\n", voltage );
806    return -1;
807  }
808
809  /*
810   * Select voltage range needed
811   */
812  dac_setup |= range_select << (channel * 2);
813  rtd6425_outport_word( rtd6425_base + RTD6425_DA_SETUP, dac_setup );
814
815  /*
816   * Now write the selected voltage
817   */
818  rtd6425_outport_word( rtd6425_base + RTD6425_DAC_BASE + (channel * 2), value );
819  return 0;
820}
821
822int rtd6425_dio_read_bit(int bit_number)
823{
824  int       dio_port;
825  uint8_t   value;
826  uint8_t   mask;
827  uint16_t  io_port;
828
829  if ( bit_number > RTD6425_DISCRETE_IO_BITS )
830    return -1;
831
832  dio_port = bit_number / 8;
833  mask     = 1 << (bit_number % 8);
834
835  switch ( dio_port ) {
836    case 0: io_port = RTD6425_PORT_0_5812;         break;
837    case 1: io_port = RTD6425_PORT_1_5812;         break;
838    case 2: io_port = RTD6425_PORT_0_5812 + 0x400; break;
839    case 3: io_port = RTD6425_PORT_1_5812 + 0x400; break;
840    default: return -1;
841  }
842
843  rtd6425_inport_byte( rtd6425_base + io_port, value );
844  return ((value & mask) ? 1 : 0);
845}
846
847int rtd6425_dio_write_bit(int bit_number, int val)
848{
849  int       dio_port;
850  uint8_t   value;
851  uint8_t   mask;
852  uint16_t  io_port;
853  uint8_t   new;
854
855  if ( bit_number > RTD6425_DISCRETE_IO_BITS )
856    return -1;
857
858  dio_port = bit_number / 8;
859  mask     = 1 << (bit_number % 8);
860  new      = ((val) ? mask : 0);
861  mask     = ~mask;
862
863  switch ( dio_port ) {
864    case 0: io_port = RTD6425_PORT_0_5812;         break;
865    case 1: io_port = RTD6425_PORT_1_5812;         break;
866    case 2: io_port = RTD6425_PORT_0_5812 + 0x400; break;
867    case 3: io_port = RTD6425_PORT_1_5812 + 0x400; break;
868    default: return -1;
869  }
870
871  rtd6425_inport_byte( rtd6425_base + io_port, value );
872  value = (value & mask) | new;
873  rtd6425_outport_byte( rtd6425_base + io_port, value );
874  return 0;
875}
876
877bool rtd6425_is_chip_irq( uint8_t chip )
878{
879  uint8_t value;
880
881  rtd6425_inport_word( rtd6425_base +  RTD6425_STATUS, value );
882  if ( (value & 0x40) == 0 )    /* XXX - Validate this is correct bit. */
883    return false;
884
885  return true;
886}
887
888/*
889 * This is the RTD6425 DIO interrupt handler. It is called by the
890 * actual hardware ISR.
891 */
892rtems_isr rtd6425_dio_handler(void *arg)
893{
894  uint8_t                 chip;
895  uint8_t                 v8;
896  uint16_t                v16;
897  rtd6425_din_message_t   din;
898  rtems_irq_connect_data *irq_conn = (rtems_irq_connect_data *)arg;
899  uint16_t                base;
900
901  rtems_clock_get_uptime( &din.timestamp );
902
903printk("DIO ISR\n");
904
905  chip = (irq_conn == & rtd6425_dio_cd0) ? 0 : 1;
906  base = rtd6425_base + (chip * 0x400);
907
908  /* check pins changed for chip n, port 1 */
909  rtd6425_inport_word( base + RTD6425_PORT_0_5812, v8 );
910  rtd6425_dio_check_pin_change(
911    (chip == 0) ? 0 : 16,                 /* pins 0-7 or 16-23 */
912    rtd6425_info[chip].previous,          /* last value we saw */
913    v8,                                   /* current value */
914    rtd6425_info[chip].irqmask,           /* pins we care about */
915    &din                                  /* message */
916  );
917  rtd6425_info[chip].previous = v8;
918
919  /* ClearIRQ16425 */
920  rtd6425_outport_word( base + RTD6425_CLEAR, (0x0040<<chip) );
921  rtd6425_inport_word( base + RTD6425_CLEAR, v16 );
922
923  /* ClearIrq5812(PORTSELECT01); */
924  rtd6425_DIO_select_register( chip, 0 );
925  rtd6425_inport_byte( base  + RTD6425_CLEAR_5812, v8 );
926
927  rtd6425_clear_Irq5812(chip);
928  rtd6425_clear_Irq6425();
929
930  if ( irq_conn->name >= 8 ) {
931    rtd6425_outport_byte( 0x20, 0x20 );
932  } else {
933    rtd6425_outport_byte( 0xA0, 0x20 );
934  }
935
936  #ifdef DEBUG
937    DEBUG_PRINT("<1>Buffering DIO interrupt on bit %d\n",int_num);
938  #endif
939}
Note: See TracBrowser for help on using the repository browser.