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; }