#include "rtapi.h"
#include "rtapi_app.h"
#include "hal.h"
#define FASTIO
#ifdef FASTIO
#define rtapi_inb inb
#define rtapi_outb outb
#include <asm/io.h>
#endif
MODULE_AUTHOR("Alex Joni");
MODULE_DESCRIPTION("Driver for Tiro-PC104 board for EMC HAL");
MODULE_LICENSE("GPL");
static int base = 0x300;
RTAPI_MP_INT(base, "board base address");
static int num_chan = 4;
RTAPI_MP_INT(num_chan, "number of channels");
typedef struct {
hal_s32_t *count;
hal_float_t *pos;
hal_float_t pos_scale;
} counter_t;
static counter_t *counter_array;
static int comp_id;
#define DATA(x) (base + (2 * x))
#define CTRL(x) (base + (2 * x) + 1)
static int export_counter(int num, counter_t * addr);
static void capture(void *arg, long period);
static int LS7166Init(int ch);
static long LS7166Read(int i);
#define MAX_CHAN 4
int rtapi_app_main(void)
{
int n, retval;
if ((num_chan <= 0) || (num_chan > MAX_CHAN)) {
rtapi_print_msg(RTAPI_MSG_ERR,
"TIRO: ERROR: invalid num_chan: %d\n", num_chan);
return -1;
}
comp_id = hal_init("hal_tiro");
if (comp_id < 0) {
rtapi_print_msg(RTAPI_MSG_ERR, "TIRO: ERROR: hal_init() failed\n");
return -1;
}
counter_array = hal_malloc(num_chan * sizeof(counter_t));
if (counter_array == 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"TIRO: ERROR: hal_malloc() failed\n");
hal_exit(comp_id);
return -1;
}
for (n = 0; n < num_chan; n++) {
retval = export_counter(n, &(counter_array[n]));
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"TIRO: ERROR: counter %d var export failed\n", n + 1);
hal_exit(comp_id);
return -1;
}
*(counter_array[n].count) = 0;
*(counter_array[n].pos) = 0.0;
counter_array[n].pos_scale = 1.0;
LS7166Init(n);
}
retval = hal_export_funct("tiro.capture-position", capture,
counter_array, 1, 0, comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"TIRO: ERROR: capture funct export failed\n");
hal_exit(comp_id);
return -1;
}
rtapi_print_msg(RTAPI_MSG_INFO,
"TIRO: installed %d encoder counters\n", num_chan);
hal_ready(comp_id);
return 0;
}
void rtapi_app_exit(void)
{
hal_exit(comp_id);
}
static void capture(void *arg, long period)
{
counter_t *cntr;
int n;
cntr = arg;
for (n = 0; n < num_chan; n++) {
*(cntr->count) = LS7166Read(n);
*(cntr->pos) = *(cntr->count) * cntr->pos_scale;
cntr++;
}
}
int LS7166Init(int ch)
{
rtapi_outb(CTRL(ch), 0x49);
rtapi_outb(CTRL(ch), 0xC3);
rtapi_outb(CTRL(ch), 0x80);
return 0;
}
long LS7166Read(int i)
{
union pos_tag {
long l;
struct byte_tag { char b0; char b1; char b2; char b3;} byte;
} pos;
rtapi_outb(CTRL(i), 0x03);
pos.byte.b0=rtapi_inb(DATA(i));
pos.byte.b1=rtapi_inb(DATA(i));
pos.byte.b2=rtapi_inb(DATA(i));
if (pos.byte.b2 < 0) {
pos.byte.b3 = -1;
}
else {
pos.byte.b3 = 0;
}
return pos.l;
}
static int export_counter(int num, counter_t * addr)
{
int retval, msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level(RTAPI_MSG_WARN);
retval = hal_pin_s32_newf(HAL_OUT, &(addr->count), comp_id,
"tiro.%d.counts", num);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_OUT, &(addr->pos), comp_id,
"tiro.%d.position", num);
if (retval != 0) {
return retval;
}
retval = hal_param_float_newf(HAL_RW, &(addr->pos_scale), comp_id,
"tiro.%d.position-scale", num);
if (retval != 0) {
return retval;
}
rtapi_set_msg_level(msg);
return 0;
}