Signed-off-by: Andy Pugh <[email protected]>
---
src/Makefile | 1 +
src/hal/drivers/mesa-hostmot2/bspi.c | 360 ++++++++++++++++++++++++++++++
src/hal/drivers/mesa-hostmot2/hostmot2.c | 33 +++
src/hal/drivers/mesa-hostmot2/hostmot2.h | 54 +++++-
src/hal/drivers/mesa-hostmot2/pins.c | 17 ++
src/hal/drivers/mesa-hostmot2/tram.c | 16 +-
6 files changed, 470 insertions(+), 11 deletions(-)
mode change 100644 => 100755 src/Makefile
create mode 100755 src/hal/drivers/mesa-hostmot2/bspi.c
mode change 100644 => 100755 src/hal/drivers/mesa-hostmot2/hostmot2.c
mode change 100644 => 100755 src/hal/drivers/mesa-hostmot2/hostmot2.h
mode change 100644 => 100755 src/hal/drivers/mesa-hostmot2/pins.c
mode change 100644 => 100755 src/hal/drivers/mesa-hostmot2/tram.c
diff --git a/src/Makefile b/src/Makefile
old mode 100644
new mode 100755
index 15c1ccd..0ad476c
--- a/src/Makefile
+++ b/src/Makefile
@@ -714,6 +714,7 @@ hostmot2-objs := \
hal/drivers/mesa-hostmot2/mesa_7i64.o \
hal/drivers/mesa-hostmot2/mesa_other_sserial.o \
hal/drivers/mesa-hostmot2/stepgen.o \
+ hal/drivers/mesa-hostmot2/bspi.o \
hal/drivers/mesa-hostmot2/watchdog.o \
hal/drivers/mesa-hostmot2/pins.o \
hal/drivers/mesa-hostmot2/led.o \
diff --git a/src/hal/drivers/mesa-hostmot2/bspi.c
b/src/hal/drivers/mesa-hostmot2/bspi.c
new file mode 100755
index 0000000..292f1c6
--- /dev/null
+++ b/src/hal/drivers/mesa-hostmot2/bspi.c
@@ -0,0 +1,360 @@
+//
+// Copyright (C) 2011 Andy Pugh
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#include <linux/slab.h>
+#include "rtapi.h"
+#include "rtapi_app.h"
+#include "rtapi_string.h"
+#include "rtapi_math.h"
+#include "hal.h"
+#include "hostmot2.h"
+
+int hm2_bspi_parse_md(hostmot2_t *hm2, int md_index)
+{
+ // All this function actually does is allocate memory
+ // and give the bspi modules names.
+
+
+ //
+ // some standard sanity checks
+ //
+
+ int i, j, r;
+ hm2_module_descriptor_t *md = &hm2->md[md_index];
+
+ if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 3, 0x40, 0x0007)) {
+ HM2_ERR("inconsistent Module Descriptor!\n");
+ return -EINVAL;
+ }
+
+ if (hm2->bspi.num_instances != 0) {
+ HM2_ERR(
+ "found duplicate Module Descriptor for %s (inconsistent "
+ "firmware), not loading driver\n",
+ hm2_get_general_function_name(md->gtag)
+ );
+ return -EINVAL;
+ }
+
+ if (hm2->config.num_bspis > md->instances) {
+ HM2_ERR(
+ "config defines %d bspis, but only %d are available, "
+ "not loading driver\n",
+ hm2->config.num_bspis,
+ md->instances
+ );
+ return -EINVAL;
+ }
+
+ if (hm2->config.num_bspis == 0) {
+ return 0;
+ }
+
+ //
+ // looks good, start initializing
+ //
+
+ if (hm2->config.num_bspis == -1) {
+ hm2->bspi.num_instances = md->instances;
+ } else {
+ hm2->bspi.num_instances = hm2->config.num_bspis;
+ }
+
+ hm2->bspi.instance = (hm2_bspi_instance_t
*)hal_malloc(hm2->bspi.num_instances
+ *
sizeof(hm2_bspi_instance_t));
+ if (hm2->bspi.instance == NULL) {
+ HM2_ERR("out of memory!\n");
+ r = -ENOMEM;
+ goto fail0;
+ }
+
+ for (i = 0 ; i < hm2->bspi.num_instances ; i++){
+ hm2_bspi_instance_t *chan = &hm2->bspi.instance[i];
+ chan->clock_freq = md->clock_freq;
+ r = sprintf(chan->name, "%s.bspi.%01d", hm2->llio->name, i);
+ HM2_PRINT("created Buffered SPI function %s.\n", chan->name);
+ chan->base_address = md->base_address + i * md->instance_stride;
+ chan->register_stride = md->register_stride;
+ chan->instance_stride = md->instance_stride;
+ chan->cd_addr = md->base_address + md->register_stride + i *
sizeof(u32);
+ chan->count_addr = md->base_address + 2 * md->register_stride + i *
sizeof(u32);
+ for (j = 0 ; j < 16 ; j++ ){
+ chan->addr[j] = chan->base_address + j * sizeof(u32);
+ }
+
+ }
+ return hm2->bspi.num_instances;
+fail0:
+ return 0;
+}
+
+void hm2_bspi_force_write(hostmot2_t *hm2)
+{
+ int i, j;
+ for (i = 0 ; i < hm2->bspi.num_instances ; i++){
+ hm2_bspi_instance_t chan = hm2->bspi.instance[i];
+ // write the channel descriptors
+ for (j = 15 ; j >=0 ; j--){
+ hm2->llio->write(hm2->llio, chan.cd_addr, &(chan.cd[j]),
sizeof(u32));
+ }
+ }
+}
+
+EXPORT_SYMBOL_GPL(hm2_tram_add_bspi_frame);
+int hm2_tram_add_bspi_frame(char *name, int chan, u32 **wbuff, u32 **rbuff)
+{
+ hostmot2_t *hm2;
+ int i, r;
+ i = hm2_get_bspi(&hm2, name);
+ if (i < 0){
+ HM2_ERR_NO_LL("Can not find BSPI instance %s.\n", name);
+ return -1;
+ }
+ if (hm2->bspi.instance[i].conf_flag[chan] != true){
+ HM2_ERR("The selected write channel (%i) on bspi instance %s.\n"
+ "Has not been configured.\n", chan, name);
+ return -1;
+ }
+ if (wbuff != NULL) {
+ r =
hm2_register_tram_write_region(hm2,hm2->bspi.instance[i].addr[chan],
sizeof(u32),wbuff);
+ if (r < 0) {
+ HM2_ERR("Failed to add TRAM write entry for %s.\n", name);
+ return -1;
+ }
+ } else {
+ HM2_ERR("SPI frame must have a write entry for channel (%i) on %s.\n",
chan, name);
+ return -1;
+ }
+ if (rbuff != NULL){
+ // Don't add a read entry for a no-echo channel
+ if(!(hm2->bspi.instance[i].cd[chan] & 0x80000000)) {
+ r =
hm2_register_tram_read_region(hm2,hm2->bspi.instance[i].addr[0],
sizeof(u32),rbuff);
+ if (r < 0) {
+ HM2_ERR( "Failed to add TRAM read entry for %s\n", name);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(hm2_allocate_bspi_tram);
+int hm2_allocate_bspi_tram(char* name)
+{
+ hostmot2_t *hm2;
+ int i, r;
+ i = hm2_get_bspi(&hm2, name);
+ if (i < 0){
+ HM2_ERR_NO_LL("Can not find BSPI instance %s.\n", name);
+ return -1;
+ }
+ r = hm2_allocate_tram_regions(hm2);
+ if (r < 0) {
+ HM2_ERR("Failed to register TRAM for BSPI %s\n", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(hm2_bspi_write_chan);
+int hm2_bspi_write_chan(char* name, int chan, u32 val)
+{
+ hostmot2_t *hm2;
+ u32 buff;
+ int i, r;
+ i = hm2_get_bspi(&hm2, name);
+ if (i < 0){
+ HM2_ERR_NO_LL("Can not find BSPI instance %s.\n", name);
+ return -1;
+ }
+ if (hm2->bspi.instance[i].conf_flag[chan] != true){
+ HM2_ERR("The selected write channel (%i) on bspi instance %s.\n"
+ "Has not been configured.\n", chan, name);
+ return -1;
+ }
+ r = hm2->llio->write(hm2->llio, hm2->bspi.instance[i].addr[chan], &buff,
sizeof(u32));
+ if (r < 0) {
+ HM2_ERR("BSPI: hm2->llio->write failure %s\n", name);
+ }
+
+ return r;
+}
+
+EXPORT_SYMBOL_GPL(hm2_bspi_setup_chan);
+int hm2_bspi_setup_chan(char *name, int chan, int cs, int bits, float mhz,
+ int delay, int cpol, int cpha, int clear, int echo)
+{
+ hostmot2_t *hm2;
+ u32 buff;
+ int i;
+ float board_mhz;
+ i = hm2_get_bspi(&hm2, name);
+ if (i < 0){
+ HM2_ERR_NO_LL("Can not find BSPI instance %s.\n", name);
+ return -1;
+ }
+ if (chan<0 || chan > 15){
+ HM2_ERR("BSPI %s: Channel number (%i) is out of range, BSPI only"
+ "supports channels 0-15\n", name, chan);
+ return -1;
+ }
+ if (cs > 15 || cs < 0){
+ HM2_ERR("BSPI %s: Chip Select for channel %i (%i) out of range, only "
+ "values 0 - 15 are accepted\n", name, chan, cs);
+ return -1;
+ }
+ if (bits > 64 || bits < 1){
+ HM2_ERR("BSPI %s: Number of bits for chan %i (%i) is out of range, "
+ "BSPI only supports 1-64 bits\n", name, chan, bits);
+ return -1;
+ }
+ if (delay < 0 || delay > 1e6){
+ HM2_ERR("The requested frame delay on channel %i of %inS seems "
+ "rather implausible for an SPI device. Exiting.\n", delay,
chan);
+ return -1;
+ }
+ board_mhz = hm2->bspi.instance[i].clock_freq / 1e6;
+
+ // reduce clock rate of the FPGA isn't fast enough
+ if (mhz > board_mhz/2){
+ mhz=board_mhz/2;
+ }
+
+ buff = (echo != 0) << 31
+ | (clear != 0) << 30
+ | ((delay <= 0)? 0x10 : (u32)((delay*board_mhz/1000.0)-1) & 0x1f) << 24
+ | (cs & 0xF) << 16
+ | (((u16)(board_mhz / (mhz * 2) - 1) & 0xF)) << 8
+ | (cpha != 0) << 7
+ | (cpol != 0) << 6
+ | (((u16)(bits - 1)) & 0x1F);
+ HM2_DBG("BSPI %s Channel %i setup %x\n", name, chan, buff);
+ hm2->bspi.instance[i].cd[chan] = buff;
+ hm2->bspi.instance[i].conf_flag[chan] = true;
+ hm2_bspi_force_write(hm2);
+ return 0;
+}
+
+void hm2_bspi_print_module(hostmot2_t *hm2){
+ int i,j;
+ HM2_PRINT("Buffered SPI: %d\n", hm2->bspi.num_instances);
+ if (hm2->bspi.num_instances <= 0) return;
+ HM2_PRINT(" version: %d\n", hm2->bspi.version);
+ HM2_PRINT(" channel configurations\n");
+ for (i = 0; i < hm2->bspi.num_instances; i ++) {
+ HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n",
+ hm2->bspi.instance[i].clock_freq,
+ hm2_hz_to_mhz(hm2->bspi.instance[i].clock_freq));
+ HM2_PRINT(" instance %d:\n", i);
+ HM2_PRINT(" HAL name = %s\n", hm2->bspi.instance[i].name);
+ for (j = 0; j < 16 ; j++){
+ HM2_PRINT(" frame %i config = %08x\n", j,
+ hm2->bspi.instance[i].cd[j]);
+ HM2_PRINT(" address = %08x\n",
+ hm2->bspi.instance[i].addr[j]);
+ }
+ }
+}
+
+EXPORT_SYMBOL_GPL(hm2_bspi_set_read_function);
+int hm2_bspi_set_read_function(char *name, void *func, void *subdata){
+ hostmot2_t *hm2;
+ int i;
+ i = hm2_get_bspi(&hm2, name);
+ if (i < 0){
+ HM2_ERR_NO_LL("Can not find BSPI instance %s.\n", name);
+ return -1;
+ }
+ if (func == NULL) {
+ HM2_ERR("Invalid function pointer passed to "
+ "hm2_bspi_set_read_function.\n");
+ return -1;
+ }
+ if (subdata == NULL) {
+ HM2_ERR("Invalid data pointer passed to "
+ "hm2_bspi_set_read_function.\n");
+ return -1;
+ }
+ hm2->bspi.instance[i].read_function = func;
+ hm2->bspi.instance[i].subdata = subdata;
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(hm2_bspi_set_write_function);
+int hm2_bspi_set_write_function(char *name, void *func, void *subdata){
+ hostmot2_t *hm2;
+ int i;
+ i = hm2_get_bspi(&hm2, name);
+ if (i < 0){
+ HM2_ERR_NO_LL("Can not find BSPI instance %s.\n", name);
+ return -1;
+ }
+ if (func == NULL) {
+ HM2_ERR("Invalid function pointer passed to "
+ "hm2_bspi_set_write_function.\n");
+ return -1;
+ }
+ if (subdata == NULL) {
+ HM2_ERR("Invalid data pointer passed to "
+ "hm2_bspi_set_write_function.\n");
+ return -1;
+ }
+ hm2->bspi.instance[i].write_function = func;
+ hm2->bspi.instance[i].subdata = subdata;
+ return 0;
+}
+
+
+void hm2_bspi_process_tram_read(hostmot2_t *hm2, long period)
+{
+ int i, r;
+ int (*func)(void *subdata);
+ for (i = 0 ; i < hm2->bspi.num_instances ; i++ ){
+ func = hm2->bspi.instance[i].read_function;
+ if (func != NULL){
+ r = func(hm2->bspi.instance[i].subdata);
+ }
+ }
+}
+
+void hm2_bspi_prepare_tram_write(hostmot2_t *hm2, long period)
+{
+ int i, r;
+ int (*func)(void *subdata);
+ for (i = 0 ; i < hm2->bspi.num_instances ; i++ ){
+ func = hm2->bspi.instance[i].write_function;
+ if (func != NULL){
+ r = func(hm2->bspi.instance[i].subdata);
+ }
+ }
+}
+
+// The following standard Hostmot2 functions are not currently used by bspi.
+
+void hm2_bspi_cleanup(hostmot2_t *hm2)
+{
+}
+
+void hm2_bspi_write(hostmot2_t *hm2)
+{
+}
+
+
+
diff --git a/src/hal/drivers/mesa-hostmot2/hostmot2.c
b/src/hal/drivers/mesa-hostmot2/hostmot2.c
old mode 100644
new mode 100755
index 70f9b3e..c4a38ad
--- a/src/hal/drivers/mesa-hostmot2/hostmot2.c
+++ b/src/hal/drivers/mesa-hostmot2/hostmot2.c
@@ -86,6 +86,7 @@ static void hm2_read(void *void_hm2, long period) {
hm2_encoder_process_tram_read(hm2, period);
hm2_stepgen_process_tram_read(hm2, period);
hm2_sserial_process_tram_read(hm2, period);
+ hm2_bspi_process_tram_read(hm2, period);
hm2_tp_pwmgen_read(hm2); // check the status of the fault bit
hm2_raw_read(hm2);
@@ -106,6 +107,7 @@ static void hm2_write(void *void_hm2, long period) {
hm2_tp_pwmgen_prepare_tram_write(hm2);
hm2_stepgen_prepare_tram_write(hm2, period);
hm2_sserial_prepare_tram_write(hm2, period);
+ hm2_bspi_prepare_tram_write(hm2, period);
hm2_tram_write(hm2);
// these usually do nothing
@@ -167,6 +169,22 @@ const char *hm2_hz_to_mhz(u32 freq_hz) {
return mhz_str;
}
+// FIXME: It would be nice if this was more generic
+EXPORT_SYMBOL_GPL(hm2_get_bspi);
+int hm2_get_bspi(hostmot2_t** hm2, char *name){
+ struct list_head *ptr;
+ int i;
+ list_for_each(ptr, &hm2_list) {
+ *hm2 = list_entry(ptr, hostmot2_t, list);
+ if ((*hm2)->bspi.num_instances > 0) {
+ for (i = 0; i <= (*hm2)->bspi.num_instances ; i++) {
+ if (!strcmp((*hm2)->bspi.instance[i].name, name)) {return i;}
+ }
+ }
+ }
+ return -1;
+}
+
// FIXME: the static automatic string makes this function non-reentrant
const char *hm2_get_general_function_name(int gtag) {
@@ -182,9 +200,11 @@ const char *hm2_get_general_function_name(int gtag) {
case HM2_GTAG_MUXED_ENCODER: return "Muxed Encoder";
case HM2_GTAG_MUXED_ENCODER_SEL: return "Muxed Encoder Select";
case HM2_GTAG_SMARTSERIAL: return "Smart Serial Interface";
+ case HM2_GTAG_BSPI: return "Buffered SPI Interface";
default: {
static char unknown[100];
rtapi_snprintf(unknown, 100, "(unknown-gtag-%d)", gtag);
+ HM2_ERR_NO_LL("Firmware contains unknown function (gtag-%d)/n",
gtag);
return unknown;
}
}
@@ -206,6 +226,7 @@ static int hm2_parse_config_string(hostmot2_t *hm2, char
*config_string) {
hm2->config.num_sserial_chans[2] = 0;
hm2->config.num_sserial_chans[3] = 0;
hm2->config.num_stepgens = -1;
+ hm2->config.num_bspis = -1;
hm2->config.num_leds = -1;
hm2->config.enable_raw = 0;
hm2->config.firmware = NULL;
@@ -252,6 +273,10 @@ static int hm2_parse_config_string(hostmot2_t *hm2, char
*config_string) {
token += 13;
hm2->config.num_stepgens = simple_strtol(token, NULL, 0);
+ } else if (strncmp(token, "num_bspis=", 10) == 0) {
+ token += 10;
+ hm2->config.num_bspis = simple_strtol(token, NULL, 0);
+
} else if (strncmp(token, "num_leds=", 9) == 0) {
token += 9;
hm2->config.num_leds = simple_strtol(token, NULL, 0);
@@ -280,6 +305,7 @@ static int hm2_parse_config_string(hostmot2_t *hm2, char
*config_string) {
hm2->config.num_sserial_chans[1], hm2->config.num_sserial_chans[2],
hm2->config.num_sserial_chans[3]);
HM2_DBG(" num_stepgens=%d\n", hm2->config.num_stepgens);
+ HM2_DBG(" num_bspis=%d\n", hm2->config.num_bspis);
HM2_DBG(" enable_raw=%d\n", hm2->config.enable_raw);
HM2_DBG(" firmware=%s\n", hm2->config.firmware ? hm2->config.firmware
: "(NULL)");
@@ -670,6 +696,10 @@ static int hm2_parse_module_descriptors(hostmot2_t *hm2) {
case HM2_GTAG_SMARTSERIAL:
md_accepted = hm2_sserial_parse_md(hm2, md_index);
break;
+
+ case HM2_GTAG_BSPI:
+ md_accepted = hm2_bspi_parse_md(hm2, md_index);
+ break;
case HM2_GTAG_LED:
md_accepted = hm2_led_parse_md(hm2, md_index);
@@ -730,6 +760,7 @@ static void hm2_cleanup(hostmot2_t *hm2) {
hm2_tp_pwmgen_cleanup(hm2);
hm2_led_cleanup(hm2);
hm2_sserial_cleanup(hm2);
+ hm2_bspi_cleanup(hm2);
// free all the tram entries
hm2_tram_cleanup(hm2);
@@ -744,6 +775,7 @@ void hm2_print_modules(hostmot2_t *hm2) {
hm2_tp_pwmgen_print_module(hm2);
hm2_sserial_print_module(hm2);
hm2_stepgen_print_module(hm2);
+ hm2_bspi_print_module(hm2);
hm2_ioport_print_module(hm2);
hm2_watchdog_print_module(hm2);
}
@@ -1348,5 +1380,6 @@ void hm2_force_write(hostmot2_t *hm2) {
hm2_stepgen_force_write(hm2);
hm2_tp_pwmgen_force_write(hm2);
hm2_sserial_force_write(hm2);
+ hm2_bspi_force_write(hm2);
}
diff --git a/src/hal/drivers/mesa-hostmot2/hostmot2.h
b/src/hal/drivers/mesa-hostmot2/hostmot2.h
old mode 100644
new mode 100755
index fe67d5d..f9d9627
--- a/src/hal/drivers/mesa-hostmot2/hostmot2.h
+++ b/src/hal/drivers/mesa-hostmot2/hostmot2.h
@@ -82,7 +82,6 @@ char **argv_split(gfp_t gfp, const char *str, int *argcp);
#define HM2_MAX_MODULE_DESCRIPTORS (48)
#define HM2_MAX_PIN_DESCRIPTORS (1000)
-
//
// Pin Descriptor constants
//
@@ -104,6 +103,7 @@ char **argv_split(gfp_t gfp, const char *str, int *argcp);
#define HM2_GTAG_STEPGEN (5)
#define HM2_GTAG_PWMGEN (6)
#define HM2_GTAG_TRANSLATIONRAM (11)
+#define HM2_GTAG_BSPI (14)
#define HM2_GTAG_TPPWM (19)
#define HM2_GTAG_LED (128)
#define HM2_GTAG_MUXED_ENCODER (12)
@@ -721,7 +721,35 @@ typedef struct {
u32 master_dds_addr;
} hm2_stepgen_t;
+//
+// Buffered SPI transciever
+//
+typedef struct {
+ u32 cd[16];
+ u16 addr[16];
+ int conf_flag[16];
+ u16 cd_addr;
+ u16 count_addr;
+ hal_u32_t *count;
+ int num_frames;
+ u32 clock_freq;
+ u16 base_address;
+ u32 register_stride;
+ u32 instance_stride;
+ char name[HAL_NAME_LEN+1];
+ void *read_function;
+ void *write_function;
+ void *subdata;
+} hm2_bspi_instance_t;
+
+typedef struct {
+ int version;
+ int num_instances;
+ hm2_bspi_instance_t *instance;
+ u8 instances;
+ u8 num_registers;
+} hm2_bspi_t;
//
@@ -834,6 +862,7 @@ typedef struct {
int num_stepgens;
int num_leds;
int num_sserials;
+ int num_bspis;
int num_sserial_chans[4];
int enable_raw;
char *firmware;
@@ -865,6 +894,7 @@ typedef struct {
hm2_tp_pwmgen_t tp_pwmgen;
hm2_stepgen_t stepgen;
hm2_sserial_t sserial;
+ hm2_bspi_t bspi;
hm2_ioport_t ioport;
hm2_watchdog_t watchdog;
hm2_led_t led;
@@ -875,8 +905,6 @@ typedef struct {
} hostmot2_t;
-
-
//
// misc little helper functions
//
@@ -1046,6 +1074,26 @@ void hm2_stepgen_process_tram_read(hostmot2_t *hm2, long
period);
void hm2_stepgen_allocate_pins(hostmot2_t *hm2);
+//
+// Buffered SPI functions
+//
+
+int hm2_bspi_parse_md(hostmot2_t *hm2, int md_index);
+void hm2_bspi_print_module(hostmot2_t *hm2);
+void hm2_bspi_cleanup(hostmot2_t *hm2);
+void hm2_bspi_write(hostmot2_t *hm2);
+void hm2_bspi_force_write(hostmot2_t *hm2);
+void hm2_bspi_prepare_tram_write(hostmot2_t *hm2, long period);
+void hm2_bspi_process_tram_read(hostmot2_t *hm2, long period);
+int hm2_allocate_bspi_tram(char* name);
+int hm2_bspi_write_chan(char* name, int chan, u32 val);
+int hm2_get_bspi(hostmot2_t **hm2, char *name); // actually in hostmot.c
+int hm2_allocate_bspi_tram(char* name);
+int hm2_tram_add_bspi_frame(char *name, int chan, u32 **wbuff, u32 **rbuff);
+int hm2_bspi_setup_chan(char *name, int chan, int cs, int bits, float mhz,
+ int delay, int cpol, int cpha, int clear, int echo);
+int hm2_bspi_set_read_function(char *name, void *func, void *subdata);
+int hm2_bspi_set_write_function(char *name, void *func, void *subdata);
//
diff --git a/src/hal/drivers/mesa-hostmot2/pins.c
b/src/hal/drivers/mesa-hostmot2/pins.c
old mode 100644
new mode 100755
index 4e512f7..4a7fa52
--- a/src/hal/drivers/mesa-hostmot2/pins.c
+++ b/src/hal/drivers/mesa-hostmot2/pins.c
@@ -138,6 +138,22 @@ static const char* hm2_get_pin_secondary_name(hm2_pin_t
*pin) {
}
break;
}
+ case HM2_GTAG_BSPI:
+ switch (sec_pin) {
+ case 0x1: return "/Frame";
+ case 0x2: return "Serial Out";
+ case 0x3: return "Clock";
+ case 0x4: return "Serial In";
+ case 0x5: return "CS0";
+ case 0x6: return "CS1";
+ case 0x7: return "CS2";
+ case 0x8: return "CS3";
+ case 0x9: return "CS4";
+ case 0xA: return "CS5";
+ case 0xB: return "CS6";
+ case 0xC: return "CS7";
+ }
+ break;
}
rtapi_snprintf(unknown, sizeof(unknown), "unknown-pin-%d", sec_pin & 0x7F);
return unknown;
@@ -397,6 +413,7 @@ void hm2_configure_pins(hostmot2_t *hm2) {
hm2_pins_allocate_all(hm2, HM2_GTAG_ENCODER, hm2->encoder.num_instances);
hm2_pins_allocate_all(hm2, HM2_GTAG_PWMGEN, hm2->pwmgen.num_instances);
hm2_pins_allocate_all(hm2, HM2_GTAG_TPPWM, hm2->tp_pwmgen.num_instances);
+ hm2_pins_allocate_all(hm2, HM2_GTAG_BSPI, hm2->bspi.num_instances);
// sserial.num_instances counts active insts, so use config.num_sserial
hm2_pins_allocate_all(hm2, HM2_GTAG_SMARTSERIAL,
hm2->config.num_sserials);
// muxed encoder gets the sel pins
diff --git a/src/hal/drivers/mesa-hostmot2/tram.c
b/src/hal/drivers/mesa-hostmot2/tram.c
old mode 100644
new mode 100755
index 8172c78..15a496d
--- a/src/hal/drivers/mesa-hostmot2/tram.c
+++ b/src/hal/drivers/mesa-hostmot2/tram.c
@@ -84,7 +84,7 @@ int hm2_register_tram_write_region(hostmot2_t *hm2, u16 addr,
u16 size, u32 **bu
int hm2_allocate_tram_regions(hostmot2_t *hm2) {
struct list_head *ptr;
u16 offset;
-
+
hm2->tram_read_size = 0;
list_for_each(ptr, &hm2->tram_read_entries) {
hm2_tram_entry_t *tram_entry = list_entry(ptr, hm2_tram_entry_t, list);
@@ -103,18 +103,18 @@ int hm2_allocate_tram_regions(hostmot2_t *hm2) {
hm2->tram_write_size
);
- hm2->tram_read_buffer = (u32 *)kmalloc(hm2->tram_read_size, GFP_KERNEL);
+ hm2->tram_read_buffer = (u32 *)krealloc(hm2->tram_read_buffer,
hm2->tram_read_size, GFP_KERNEL);
if (hm2->tram_read_buffer == NULL) {
- HM2_ERR("out of memory while allocating Translation RAM read buffer
(%d bytes)\n", hm2->tram_read_size);
+ HM2_ERR("Error while (re)allocating Translation RAM read buffer (%d
bytes)\n", hm2->tram_read_size);
return -ENOMEM;
}
-
- hm2->tram_write_buffer = (u32 *)kmalloc(hm2->tram_write_size, GFP_KERNEL);
+
+ hm2->tram_write_buffer = (u32 *)krealloc(hm2->tram_write_buffer,
hm2->tram_write_size, GFP_KERNEL);
if (hm2->tram_write_buffer == NULL) {
- HM2_ERR("out of memory while allocating Translation RAM write buffer
(%d bytes)\n", hm2->tram_write_size);
+ HM2_ERR("Error while (re)allocating Translation RAM write buffer (%d
bytes)\n", hm2->tram_write_size);
return -ENOMEM;
}
-
+ HM2_DBG("buffer address %p\n", &hm2->tram_write_buffer);
HM2_DBG("Translation RAM read buffer:\n");
offset = 0;
list_for_each(ptr, &hm2->tram_read_entries) {
@@ -132,7 +132,7 @@ int hm2_allocate_tram_regions(hostmot2_t *hm2) {
offset += tram_entry->size;
HM2_DBG(" addr=0x%04x, size=%d, buffer=%p\n", tram_entry->addr,
tram_entry->size, *tram_entry->buffer);
}
-
+
return 0;
}
--
1.7.0.4
>From 562687efb2ad9c8be833db836807c78ebe686577 Mon Sep 17 00:00:00 2001
From: Andy Pugh <[email protected]>
Date: Thu, 21 Jul 2011 20:48:49 +0100
Subject: [PATCH 2/3] Documentation for the Hostmot2 BSPI Driver
Signed-off-by: Andy Pugh <[email protected]>
---
docs/man/man3/hm2_allocate_bspi_tram.3hm2 | 27 ++++++++++++++++
docs/man/man3/hm2_bspi_set_read_function.3hm2 | 33 +++++++++++++++++++
docs/man/man3/hm2_bspi_set_write_function.3hm2 | 34 ++++++++++++++++++++
docs/man/man3/hm2_bspi_setup_chan.3hm2 | 40 ++++++++++++++++++++++++
docs/man/man3/hm2_bspi_write_chan.3hm2 | 29 +++++++++++++++++
docs/man/man3/hm2_tram_add_bspi_frame.3hm2 | 31 ++++++++++++++++++
docs/man/man9/hostmot2.9 | 18 +++++++++++
7 files changed, 212 insertions(+), 0 deletions(-)
create mode 100755 docs/man/man3/hm2_allocate_bspi_tram.3hm2
create mode 100644 docs/man/man3/hm2_bspi_set_read_function.3hm2
create mode 100644 docs/man/man3/hm2_bspi_set_write_function.3hm2
create mode 100755 docs/man/man3/hm2_bspi_setup_chan.3hm2
create mode 100755 docs/man/man3/hm2_bspi_write_chan.3hm2
create mode 100755 docs/man/man3/hm2_tram_add_bspi_frame.3hm2
mode change 100644 => 100755 docs/man/man9/hostmot2.9
diff --git a/docs/man/man3/hm2_allocate_bspi_tram.3hm2
b/docs/man/man3/hm2_allocate_bspi_tram.3hm2
new file mode 100755
index 0000000..d87d560
--- /dev/null
+++ b/docs/man/man3/hm2_allocate_bspi_tram.3hm2
@@ -0,0 +1,27 @@
+.TH hm2_allocate_bspi_tram "3hm2" "2011-05-31" "EMC Documentation" "Hostmot2"
+.SH NAME
+
+hm2_allocate_bspi_tram \- Allocate the TRAM regions for a BSPI channel
+
+.SH SYNTAX
+.HP
+hm2_allocate_bspi_tram(char* name)
+
+.SH DESCRIPTION
+\fBhm2_allocate_bspi_tram\fR Allocate the TRAM memory for bspi instance
"name".
+"name" is a unique string given to each bspi channel during hostmot2 setup.
+The names of the available channels are printed to standard output during the
+driver loading process and take the form:
+hm2_<board name>.<board index>.bspi.<index> For example hm2_5i23.0.bspi.0
+
+This function allocates the TRAM memory and sets up the regular data
transfers.
+It should be called only when all the frames have been defined by calls to
+hm2_tram_add_bspi_frame().
+
+.SH RETURN VALUE
+Returns 0 on success and -1 on failure.
+
+.SH SEE ALSO
+man hm2_bspi_setup_chan, man hm2_bspi_write_chan, man hm2_tram_add_bspi_frame
+man hm2_allocate_bspi_tram.
+See src/hal/drivers mesa_7i65.comp for an example usage.
diff --git a/docs/man/man3/hm2_bspi_set_read_function.3hm2
b/docs/man/man3/hm2_bspi_set_read_function.3hm2
new file mode 100644
index 0000000..cd7043d
--- /dev/null
+++ b/docs/man/man3/hm2_bspi_set_read_function.3hm2
@@ -0,0 +1,33 @@
+.TH hm2_bspi_set_read_function "3hm2" "2011-05-31" "EMC Documentation"
"Hostmot2"
+.SH NAME
+
+hm2_bspi_set_write_function \- Register a function to handle the tram write
phase
+of a hostmot2 buffered SPI driver.
+.SH SYNTAX
+.HP
+int hm2_bspi_set_read_function(char *name, void *func, void *subdata)
+
+.SH DESCRIPTION
+\fBhm2_bspi_set_read_function\fR Registers a function in an external driver
+(typically written in "comp") to be called every time that the main Hostmot2
+driver calls the generic "process_tram_read" functionsread.
+ The names of the available channels are printed to standard output during the
+driver loading process and take the form:
+hm2_<board name>.<board index>.bspi.<index> For example hm2_5i23.0.bspi.0
+ "func" should be a pointer to a function in the sub driver which is to be
+called to process the results of the BSPI TRAM read phase. The function must
+take a single argument, a pointer to an individual instance of the internal
+driver. If defined in comp then the function must /fBnot/fP use the FUNCTION()
+convenience macro, and the argument to the function in the definition must
+read/fBallways/fP be (struct state *inst).
+ "subdata" is a pointer to the driver instance internal data. In the case of a
+driver written in comp this will always be "inst" in the function call and the
+call should be anywhere in the EXTRA_SETUP code.
+
+.SH RETURN VALUE
+Returns 0 on success and -1 on failure.
+
+.SH SEE ALSO
+man hm2_bspi_setup_chan, man hm2_bspi_write_chan, man hm2_tram_add_bspi_frame
+man hm2_allocate_bspi_tram.
+See src/hal/drivers mesa_7i65.comp for an example usage.
\ No newline at end of file
diff --git a/docs/man/man3/hm2_bspi_set_write_function.3hm2
b/docs/man/man3/hm2_bspi_set_write_function.3hm2
new file mode 100644
index 0000000..114ac6f
--- /dev/null
+++ b/docs/man/man3/hm2_bspi_set_write_function.3hm2
@@ -0,0 +1,34 @@
+.TH hm2_bspi_set_write_function "3hm2" "2011-05-31" "EMC Documentation"
"Hostmot2"
+.SH NAME
+
+hm2_bspi_set_write_function \- Register a function to handle the tram write
phase
+of a hostmot2 buffered SPI driver.
+.SH SYNTAX
+.HP
+int hm2_bspi_set_write_function(char *name, void *func, void *subdata)
+
+.SH DESCRIPTION
+\fBhm2_bspi_set_write_function\fR Registers a function in an external driver
+(typically written in "comp") to be called every time that the main Hostmot2
+driver calls the generic "prepare_tram_write" functions.
+ The names of the available channels are printed to standard output during the
+driver loading process and take the form:
+hm2_<board name>.<board index>.bspi.<index> For example hm2_5i23.0.bspi.0
+ "func" should be a pointer to a function in the sub driver which is to be
+called to process the pins into BSPI write registers prior to the regular TRAM
+write phase. The function must take a single argument, a pointer to an
+individual instance of the internal driver. If defined in comp then the
+function must /fBnot/fP use the FUNCTION() convenience macro, and the argument
+to the function in the definition must /fBallways/fP be (struct state *inst).
+ "subdata" is a pointer to the driver instance internal data. In the case of a
+driver written in comp this will always be "inst" in the function call.
+ If using comp then the call to this function should be anywhare in the
+EXTRA_SETUP code.
+
+.SH RETURN VALUE
+Returns 0 on success and -1 on failure.
+
+.SH SEE ALSO
+man hm2_bspi_setup_chan, man hm2_bspi_write_chan, man hm2_tram_add_bspi_frame
+man hm2_allocate_bspi_tram.
+See src/hal/drivers mesa_7i65.comp for an example usage.
\ No newline at end of file
diff --git a/docs/man/man3/hm2_bspi_setup_chan.3hm2
b/docs/man/man3/hm2_bspi_setup_chan.3hm2
new file mode 100755
index 0000000..3cb12a1
--- /dev/null
+++ b/docs/man/man3/hm2_bspi_setup_chan.3hm2
@@ -0,0 +1,40 @@
+.TH hm2_bspi_setup_chan "3hm2" "2011-05-31" "EMC Documentation" "Hostmot2"
+.SH NAME
+
+hm2_bspi_setup_chan \- setup a Hostmot2 bspi channel
+
+.SH SYNTAX
+.HP
+int hm2_bspi_setup_chan(char *name, int chan, int cs, int bits, float mhz,
+int delay, int cpol, int cpha, int clear, int echo)
+
+.SH DESCRIPTION
+\fBhm2_bspi_setup_chan\fR Setup the bspi channel "chan" on the bspi instance
+"name". "name" is a unique string given to each bspi channel during hostmot2
+setup. The names of the available
+channels are printed to standard output during the driver loading process and
+take the form:
+hm2_<board name>.<board index>.bspi.<index> For example hm2_5i23.0.bspi.0
+Channels are numbered 0 to 15.
+The value on the chip-select lines is set by cs and need not match the
+channel number. BSPI supports 4 chip select lines, so the valid range for cs
is
+0-15. "bits" sets the bit-length of the SPI packet. The maximum supported
length
+is 64 bits but this will span two read FIFO entries and will need special
+handling. "mhz" sets the chip communication rate. The maximum value for this
is
+half the FPGA base frequency, so for example with a 48MHz 5i23 the max SPI
+frequency is 24Mhz. Values in excess of the max supported will be silently
+rounded down. "delay" sets the chip select valid delay (in nS). "cpha" is the
+clock phase and "cpol" is the clock polarity (from the device datasheet).
+"clear" controls whether the frame clear bit is set after the 32 bit buffer
+transfer. This parameter should be set to 1 when the frame length is greater
+than 32 bits and the next data in the FIFO contains the other bits. "echo" is
+sense-inverted, it should be set to 1 for devices which do not return data
(such
+ as DACs).
+
+.SH RETURN VALUE
+Returns 0 on success and -1 on failure.
+
+.SH SEE ALSO
+man hm2_bspi_setup_chan, man hm2_bspi_write_chan, man hm2_tram_add_bspi_frame
+man hm2_allocate_bspi_tram.
+See src/hal/drivers mesa_7i65.comp for an example usage.
diff --git a/docs/man/man3/hm2_bspi_write_chan.3hm2
b/docs/man/man3/hm2_bspi_write_chan.3hm2
new file mode 100755
index 0000000..4e7a6be
--- /dev/null
+++ b/docs/man/man3/hm2_bspi_write_chan.3hm2
@@ -0,0 +1,29 @@
+.TH hm2_bspi_write_chan "3hm2" "2011-05-31" "EMC Documentation" "Hostmot2"
+.SH NAME
+
+hm2_bspi_write_chan \- write data to a Hostmot2 Buffered SPI channel
+
+.SH SYNTAX
+.HP
+hm2_bspi_write_chan(char* name, int chan, u32 val)
+
+.SH DESCRIPTION
+\fBhm2_bspi_write_chan\fR write one-time data to the bspi channel "chan" on
the
+bspi instance "name". "name" is a unique string given to each bspi channel
+during hostmot2 setup. The names of the available
+channels are printed to standard output during the driver loading process and
+take the form:
+hm2_<board name>.<board index>.bspi.<index> For example hm2_5i23.0.bspi.0
+
+This function performs a one-time write of data to the specified channel. It is
+typically used for setup and chip enabling purposes. It should not be used in
+the main loop for regular data transfers (but is appropriate to use for on-the-
+fly setup changes).
+
+.SH RETURN VALUE
+Returns 0 on success and -1 on failure.
+
+.SH SEE ALSO
+man hm2_bspi_setup_chan, man hm2_bspi_write_chan, man hm2_tram_add_bspi_frame
+man hm2_allocate_bspi_tram.
+See src/hal/drivers mesa_7i65.comp for an example usage.
diff --git a/docs/man/man3/hm2_tram_add_bspi_frame.3hm2
b/docs/man/man3/hm2_tram_add_bspi_frame.3hm2
new file mode 100755
index 0000000..1ebfe14
--- /dev/null
+++ b/docs/man/man3/hm2_tram_add_bspi_frame.3hm2
@@ -0,0 +1,31 @@
+.TH hm2_tram_add_bspi_frame "3hm2" "2011-05-31" "EMC Documentation" "Hostmot2"
+.SH NAME
+
+hm2_tram_add_bspi_frame \- add a register-write to the Hostmot2 TRAM
+
+.SH SYNTAX
+.HP
+hm2_tram_add_bspi_frame(char *name, int chan, u32 **wbuff, u32 **rbuff)
+
+.SH DESCRIPTION
+\fBhm2_tram_add_bspi_frame\fR Add a regular (every thread) write event to the
+Hostmot2 tram for bspi instance "name". "name" is a unique string given to
each
+bspi channel during hostmot2 setup. The names of the available
+channels are printed to standard output during the driver loading process and
+take the form:
+hm2_<board name>.<board index>.bspi.<index> For example hm2_5i23.0.bspi.0
+
+This function is used to add a regular, every thread, write or write-read
+transaction to the Translation RAM system. A write need not have a read (use 0
+for **rbuff) but it is an error to have a read without a write. Note that the
+TRAM list is not actioned until the hm2_allocate_bspi_tram function is called.
+The read and write parameters must be pointers to pointers, as TRAM re-maps
the
+buffers into contiguous memory.
+
+.SH RETURN VALUE
+Returns 0 on success and -1 on failure.
+
+.SH SEE ALSO
+man hm2_bspi_setup_chan, man hm2_bspi_write_chan, man hm2_tram_add_bspi_frame
+man hm2_allocate_bspi_tram.
+See src/hal/drivers mesa_7i65.comp for an example usage.
diff --git a/docs/man/man9/hostmot2.9 b/docs/man/man9/hostmot2.9
old mode 100644
new mode 100755
index d047f81..d170d6b
--- a/docs/man/man9/hostmot2.9
+++ b/docs/man/man9/hostmot2.9
@@ -166,6 +166,10 @@ For this reason the feature defaults to all channels
disabled.
The parameter can also be used to disable specific channels and/
or ports.
.TP
+\fBnum_bspis\fR [optional, default: -1]
+Only enable the first N Buffered SPI drivers. If N is -1 then all the drivers
+are enabled. Each BSPI driver can address 16 devices.
+.TP
\fBnum_leds\fR [optional, default: -1]
Only enable the first N of the LEDs on the FPGA board. If N is -1, then HAL
pins for all the LEDs will be created. If N=0 then no pins will be added.
@@ -593,6 +597,20 @@ Parameters:
the output value, such that writing 0 to .gpio.NN.out will enable the output
and vice-versa.
+.SH BSPI
+The BSPI (Buffered SPI) driver is unusual in that it does not create any HAL
+pins. Instead the driver exports a set of functions that can be used by a sub
+-driver for the attached hardware. Typically these would be written in the
"comp"
+pre-processing language: see http://linuxcnc.org/docs/html/hal_comp.html or
man
+comp for further details. See man mesa_7i65 and the source of mesa_7i65.comp
for
+details of a typical sub-driver.
+See man hm2_bspi_setup_chan, man hm2_bspi_write_chan, man
hm2_tram_add_bspi_frame,
+man hm2_allocate_bspi_tram, man hm2_bspi_set_read_funtion and
+man hm2_bspi_set_write_function for the exported functions.
+
+The names of the available channels are printed to standard output during the
+driver loading process and take the form
+hm2_<board name>.<board index>.bspi.<index> For example hm2_5i23.0.bspi.0
.SH General Purpose I/O
--
1.7.0.4
>From 9053c2a760c7e8f090fe7b4cb397e5dedf038649 Mon Sep 17 00:00:00 2001
From: Andy Pugh <[email protected]>
Date: Thu, 21 Jul 2011 20:49:12 +0100
Subject: [PATCH 3/3] Add a drive for the Mesa 7i65 card
Signed-off-by: Andy Pugh <[email protected]>
---
src/hal/drivers/mesa_7i65.comp | 246 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 246 insertions(+), 0 deletions(-)
create mode 100755 src/hal/drivers/mesa_7i65.comp
diff --git a/src/hal/drivers/mesa_7i65.comp b/src/hal/drivers/mesa_7i65.comp
new file mode 100755
index 0000000..f7c2102
--- /dev/null
+++ b/src/hal/drivers/mesa_7i65.comp
@@ -0,0 +1,246 @@
+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 state *inst){
+ int i;
+ double aout[8];
+
+ // Write Misc IO & Reset Watchdog
+ *CPLD_write = 0xA00 // "write" command
+ | enable_out(7) << 7 | enable_out(6) << 6
+ | enable_out(5) << 5 | enable_out(4) << 4
+ | enable_out(3) << 3 | enable_out(2) << 2
+ | enable_out(1) << 1 | enable_out(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;
+ rtapi_set_msg_level(5);
+ // 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, inst);
+
+ // no separate write function in this example, but it would be:
+ // r += hm2_bspi_set_write_function(name, &write, inst);
+
+ if (r < 0) {
+ HM2_ERR_NO_LL("There have been %i errors during TRAM allocation setup,
"
+ "quitting\n", -r);
+ return -EINVAL;
+ }
+ rtapi_set_msg_level(1);
+ return 0;
+}
+
+int get_count(void){
+ int i;
+ for (i= 0; bspi_chans[i] != NULL && i < 16 ; i++){}
+ return i;
+}
--
1.7.0.4
------------------------------------------------------------------------------
uberSVN's rich system and user administration capabilities and model
configuration take the hassle out of deploying and managing Subversion and
the tools developers use with it. Learn more about uberSVN and get a free
download at: http://p.sf.net/sfu/wandisco-dev2dev
_______________________________________________
Emc-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/emc-developers