summaryrefslogtreecommitdiff
path: root/src/hal/drivers/mesa_7i65.comp
blob: 0cd2ae4a906684a46ec4e26700e7b7898532ec07 (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
component mesa_7i65 "Support for the Mesa 7i65 Octuple Servo Card";

description """The component takes parameters in the form of a comma-separated
list of bspi (buffered SPI) instance names, for example:

\\fB loadrt mesa_7i65 bspi_chans=hm2_5i23.0.bspi.0, hm2_5i23.0.bspi.1\\fR

The BSPI instances are printed to the dmesg buffer during the Hostmot2 setup
sequence, one for each bspi instance included in the bitfile loaded to each
installed card during the Hostmot2 setup sequence. Type "dmesg" at the terminal
prompt to view the output.""";

pin in float analogue.#.out [8] """Analogue output values. The value will be
limited to a  -1.0 to +1.0 range""";
pin out float analogue.#.in [8] "Analogue outputs read by the 7i65 (in Volts)";
pin out bit digital.#.in [4] "Miscellaneous Digital Inputs";
pin in bit enable.#.out [8] "Amplifier-enable control pins";
pin out bit watchdog.has-bit """Indicates the status of the 7i65 Watchdog (which
is separate from the FPGA card watchdog""";
param rw float scale-# [8] = 10 """Analogue output scale factor. For example if
the scale is 7 then an input of 1.0 will give 7V on the output terminals""";
param rw bit is-bipolar-# [8] = 1 """Set this value to TRUE for a plus/minus
"scale" output. Set to 0 for a 0-"scale" output""";

option extra_setup yes;
option count_function yes;

variable u32 firstrun;

variable u32 *AD5754_1A;
variable u32 *AD5754_1B;
variable u32 *AD5754_1C;
variable u32 *AD5754_1D;
variable u32 *AD5754_2A;
variable u32 *AD5754_2B;
variable u32 *AD5754_2C;
variable u32 *AD5754_2D;
variable u32 *CPLD_write;
variable u32 *CPLD_read;
variable u32 *AD7329_write[8];
variable u32 *AD7329_read[8];

license "GPL";
author "Andy Pugh / Cliff Blackburn";

include "../../../hal/drivers/mesa-hostmot2/hostmot2.h";
;;

// to parse the modparam
char *bspi_chans[16] = {0,};
RTAPI_MP_ARRAY_STRING(bspi_chans, 16, "BSPI Channel names");

static void read(struct __comp_state *__comp_inst){
    int i;
    double aout[8];

    // Write Misc IO & Reset Watchdog
    *CPLD_write = 0xA00 // "write" command
               | (enable_out(7) != 0) << 7 | (enable_out(6) != 0) << 6
               | (enable_out(5) != 0) << 5 | (enable_out(4) != 0) << 4
               | (enable_out(3) != 0) << 3 | (enable_out(2) != 0) << 2
               | (enable_out(1) != 0) << 1 | (enable_out(0) != 0);

    // Read Analog to Digital
    *AD7329_write[0] = 0x00000000;
    *AD7329_write[1] = 0x00000000;
    *AD7329_write[2] = 0x00000000;
    *AD7329_write[3] = 0x00000000;
    *AD7329_write[4] = 0x00000000;
    *AD7329_write[5] = 0x00000000;
    *AD7329_write[6] = 0x00000000;
    *AD7329_write[7] = 0x00009C18; // Reset Sequencer to 0.. jic

    // Limit DAC Outputs
    for (i = 0 ; i < 8 ; i++) {
        if (scale(i) > 10)
            scale(i) = 10;
        if (scale(i) < -10)
            scale(i) = -10;

        aout[i] = analogue_out(i);
        if (aout[i] > 1)
            aout[i] = 1;
        if (is_bipolar(i)) {
            if (aout[i] < -1)
                aout[i] = -1;
        }
        else {
            if (aout[i] < 0)
                aout[i] = 0;
        }
    }

    *AD5754_1A = 0x00000000 |  // address
                     (0x0000FFFF &  // mask
                     (u32)((s16)(aout[0] * scale(0) * 3276.799)));

    *AD5754_1B = 0x00010000 |  // address
                     (0x0000FFFF &  // mask
                     (u32)((s16)(aout[1] * scale(1) * 3276.799)));

    *AD5754_1C = 0x00020000 |  // address
                     (0x0000FFFF &  // mask
                     (u32)((s16)(aout[2] * scale(2) * 3276.799)));

    *AD5754_1D = 0x00030000 |  // address
                     (0x0000FFFF &  // mask
                     (u32)((s16)(aout[3] * scale(3) * 3276.799)));

    *AD5754_2A = 0x00000000 |  // address
                     (0x0000FFFF &  // mask
                     (u32)((s16)(aout[4] * scale(4) * 3276.799)));

    *AD5754_2B = 0x00010000 |  // address
                     (0x0000FFFF &  // mask
                     (u32)((s16)(aout[5] * scale(5) * 3276.799)));

    *AD5754_2C = 0x00020000 |  // address
                     (0x0000FFFF &  // mask
                     (u32)((s16)(aout[6] * scale(6) * 3276.799)));

    *AD5754_2D = 0x00030000 |  // address
                     (0x0000FFFF &  // mask
                     (u32)((s16)(aout[7] * scale(7) * 3276.799)));

    // Setup DAC, watchdog will have reset it if done in setup
    if(firstrun) {
       // Setup DAC
            // DAC: write - range select - all chans - +/-10V
        *AD5754_1A = 0x000C0004;
        *AD5754_2A = 0x000C0004;
            // DAC: power up all channels
        *AD5754_1B = 0x0010000F;
        *AD5754_2B = 0x0010000F;

        // NOP, Reads
        *AD5754_1C = 0x00800000;
        *AD5754_2C = 0x00800000;
        *AD5754_1D = 0x00800000;
        *AD5754_2D = 0x00800000;

        firstrun = false;
    }

    // Read Misc IO and Watchdog from CPLD
    digital_in(0) = (*CPLD_read & 0x1) ? 1:0;
    digital_in(1) = (*CPLD_read & 0x2) ? 1:0;
    digital_in(2) = (*CPLD_read & 0x4) ? 1:0;
    digital_in(3) = (*CPLD_read & 0x8) ? 1:0;
    watchdog_has_bit = (*CPLD_read & 0x100) ? 1:0;

    // Read ADC's into Pins
    for(i=0; i < 8; i++) {
        analogue_in(i) = (double)((s16)((*AD7329_read[i] & 0x1FFF) << 3)) / 3276.8;
    }
}

EXTRA_SETUP(){
    int i, r;
    char *name = bspi_chans[extra_arg]; // This is the string which identifies board and instance

    firstrun = true;
    // Set up channel descriptors
    //hm2_bspi_setup_chan(name, chan, cs, bits, mhz, delay(ns), cpol, cpha, /clear, /echo)
    // CS0 loopback Echo, CS0, ~ 4 MHz, CPOL, 32 bits
    r = hm2_bspi_setup_chan(name, 0, 0, 32, 4, 0, 1, 0, 0, 0);
    // CS1 AD5754 No echo, CS1, 25 MHz, CPOL, 24 bits
    r += hm2_bspi_setup_chan(name, 1, 1, 24, 25, 0, 1, 0, 0, 1);
    // CS2 AD5754 No echo, CS2, 25 MHz, CPOL, 24 bits
    r += hm2_bspi_setup_chan(name, 2, 2, 24, 25, 0, 1, 0, 0, 1);
    // CS3 AD7329 Echo, CS3, ~6 MHz, CPOL, 16 bits
    r += hm2_bspi_setup_chan(name, 3, 3, 16, 6, 0, 1, 0, 0, 0);
    // CS4 CPLD Echo, CS4, ~6 MHz, CPOL, 12 bits
    r += hm2_bspi_setup_chan(name, 4, 4, 12, 6, 0, 1, 0, 0, 0);
    // CS5 Not Used No echo, CS5, 25 MHz, 2 bits
    r += hm2_bspi_setup_chan(name, 5, 5, 2, 25, 0, 1, 0, 0, 1);
    // CS6 Not Used No echo, CS5, 25 MHz, 2 bits
    r += hm2_bspi_setup_chan(name, 6, 6, 2, 25, 0, 1, 0, 0, 1);
    // CS7 EEPROM Echo, CS7, ~4 MHz, CPOL,CPHA, 8 bits
    r += hm2_bspi_setup_chan(name, 7, 7, 8, 4, 0, 1, 1, 0, 0);
    // CS7 EEPROM No Echo, CS7, ~4 MHz, CPOL,CPHA, 8 bits
    r += hm2_bspi_setup_chan(name, 8, 7, 8, 4, 0, 1, 1, 0, 1);
    // CS7 EEPROM No Echo, DontClearFrame, CS7, ~4 MHz,CPOL,CPHA, 8 bits
    r += hm2_bspi_setup_chan(name, 9, 7, 8, 4, 0, 1, 1, 1, 1);

    if (r < 0) {
        HM2_ERR_NO_LL("There have been %i errors during channel setup, "
                      "quitting\n", -r);
        return -EINVAL;
    }

    // Setup ADC
        // ADC, chans 0-3 +/-10V
    r += hm2_bspi_write_chan(name, 3, 0x0000A000);
        // ADC, chans 4-7 +/-10V
    r += hm2_bspi_write_chan(name, 3, 0x0000C000);
        // ADC, Sequencer mode 2, Internal Ref, 8x Single Ended
    r += hm2_bspi_write_chan(name, 3, 0x00009C18);

    if (r < 0) {
        HM2_ERR_NO_LL("There have been %i errors during ADC setup, "
                      "quitting\n", -r);
        return -EINVAL;
    }
    // Add BSPI Frames
    r += hm2_tram_add_bspi_frame(name, 4, &CPLD_write,
                            &CPLD_read);

    for(i = 0; i < 8; i++) {
        r += hm2_tram_add_bspi_frame(name, 3, &AD7329_write[i],
                                &AD7329_read[i]);
    }

    r += hm2_tram_add_bspi_frame(name, 1, &AD5754_1A,0);
    r += hm2_tram_add_bspi_frame(name, 1, &AD5754_1B,0);
    r += hm2_tram_add_bspi_frame(name, 1, &AD5754_1C,0);
    r += hm2_tram_add_bspi_frame(name, 1, &AD5754_1D,0);
    r += hm2_tram_add_bspi_frame(name, 2, &AD5754_2A,0);
    r += hm2_tram_add_bspi_frame(name, 2, &AD5754_2B,0);
    r += hm2_tram_add_bspi_frame(name, 2, &AD5754_2C,0);
    r += hm2_tram_add_bspi_frame(name, 2, &AD5754_2D,0);

    // This is required, or nothing happens.
    r += hm2_allocate_bspi_tram(name);

    // Tell the bspi driver which function to call
    r += hm2_bspi_set_read_function(name, &read, __comp_inst);

    // no separate write function in this example, but it would be:
    // r += hm2_bspi_set_write_function(name, &write, __comp_inst);

    if (r < 0) {
        HM2_ERR_NO_LL("There have been %i errors during TRAM allocation setup, "
                      "quitting\n", -r);
        return -EINVAL;
    }
    return 0;
}

int get_count(void){
    int i;
    for (i= 0; bspi_chans[i] != NULL && i < 16 ; i++){}
    return i;
}