Commit 84e5f9de authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

Initial commit

parent 714550a6
OBJS = liboasis-usb-att.o
CFLAGS = -I. -DGIT_VERSION="dummy"
all: lib testprog
lib: $(OBJS)
ar rc liboasis-usb-att.a $(OBJS)
/**
* @file liboasis-usb-att.c
* @brief Library file for the msatt driver
* @author Tomasz Włostowski
* @date October 17th 2018
*/
#include <stdio.h>
#include <errno.h>
#include "liboasis-usb-att.h"
#include <ftdi.h>
#define OAU_VENDOR_ID 0x0403
#define OAU_DEVICE_ID 0x6010
#define OAU_MAX_HANDLES 16
#define OAU_NUM_CHANNELS 4
const char * const liboau_att_version_s = "liboasis-usb-att version: ";// GIT_VERSION;
struct oau_context {
struct ftdi_context *ftdi;
uint8_t relay_state;
};
static int oau_current_handle = 0;
static struct oau_context oau_contexts[OAU_MAX_HANDLES];
static struct {
int r1, r2;
} oau_relay_mapping[OAU_NUM_CHANNELS] = {
{ 0, 1 },
{ 2, 3 },
{ 4, 5 },
{ 6, 7 }
};
int oau_att_open(int lun)
{
int ret;
if( oau_current_handle >= OAU_MAX_HANDLES )
return -ENOMEM;
struct oau_context *ctx = &oau_contexts[ oau_current_handle ];
int fd = oau_current_handle;
oau_current_handle++;
if ((ctx->ftdi = ftdi_new()) == 0)
{
return -ENOMEM;
}
if ((ret = ftdi_usb_open(ctx->ftdi, OAU_VENDOR_ID, OAU_DEVICE_ID)) < 0)
{
ftdi_free(ctx->ftdi);
return ret;
}
if( (ret = ftdi_set_bitmode(ctx->ftdi, 0xff, BITMODE_BITBANG)) < 0 )
{
ftdi_usb_close( ctx->ftdi );
ftdi_free(ctx->ftdi);
return ret;
}
uint8_t pins;
if( (ret = ftdi_read_pins(ctx->ftdi, &pins) ) < 0 )
{
ftdi_usb_close( ctx->ftdi );
ftdi_free(ctx->ftdi);
return ret;
}
ctx->relay_state = pins;
return fd;
}
int oau_att_close (int fd)
{
struct oau_context *ctx = &oau_contexts[ fd ];
int ret;
if( (ret = ftdi_usb_close( ctx->ftdi )) < 0 )
{
return ret;
}
ftdi_free( ctx->ftdi );
return 0;
}
enum oau_att_value_enum oau_att_get_relay (int fd, int channel)
{
struct oau_context *ctx = &oau_contexts[ fd ];
if(channel < 1 || channel > OAU_NUM_CHANNELS)
return -EINVAL;
uint8_t r1_mask = 1 << oau_relay_mapping[channel-1].r1;
uint8_t r2_mask = 1 << oau_relay_mapping[channel-1].r2;
int r1 = ( ctx->relay_state & r1_mask );
int r2 = ( ctx->relay_state & r2_mask );
if( r1 && !r2 )
return ATT_1;
else if ( r1 && r2 )
return ATT_2;
else if ( !r1 && !r2 )
return ATT_NONE;
return ATT_ERR;
}
int oau_att_set_relay (int fd, int channel, enum oau_att_value_enum val)
{
struct oau_context *ctx = &oau_contexts[ fd ];
fprintf(stderr, "att_set_delay fd %d chan %d val %d\n", fd, channel, val);
if(channel < 1 || channel > OAU_NUM_CHANNELS)
return -EINVAL;
uint8_t r1_mask = 1 << oau_relay_mapping[channel-1].r1;
uint8_t r2_mask = 1 << oau_relay_mapping[channel-1].r2;
switch(val)
{
case ATT_NONE:
ctx->relay_state &= ~(r1_mask | r2_mask);
break;
case ATT_1:
ctx->relay_state &= ~r2_mask;
ctx->relay_state |= r1_mask;
break;
case ATT_2:
ctx->relay_state |= r1_mask;
ctx->relay_state |= r2_mask;
break;
default:
return -EINVAL;
}
printf("RState %x\n", ctx->relay_state );
int ret = ftdi_write_data(ctx->ftdi, &ctx->relay_state, 1);
if(ret < 0)
return -EIO;
uint8_t pins;
ftdi_read_pins(ctx->ftdi, &pins);
printf("RState2 %x\n", pins );
return 0;
}
int oau_att_get_nchannels(int fd)
{
return OAU_NUM_CHANNELS;
}
/**
* @file liboasis-usb-att.h
*
* @brief OASIS USB Attenuator driver library interface
*
* This file describes the external interface to the OASIS USB Attenuator
* driver and provides the definitios for proper communication
* with the device
*
* Copyright (c) 2018 CERN
* @author Tomasz Włostowski <tomasz.wlostowski@cern.ch>
*
* @section license_sec License
* Released under the GPL v2. (and only v2, not any later version)
*/
#ifndef __LIBOASIS_USB_ATT_H
#define __LIBOASIS_USB_ATT_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @enum oau_att_value_enum
* @brief Valid relay values
*
*/
enum oau_att_value_enum {
ATT_ERR = -1, /**< Error */
ATT_NONE = 0x0, /**< No attenuation */
ATT_1 = 0x01, /**< Attenuator 1: 20dB */
ATT_2 = 0x03, /**< Attenuator 1+2: 40dB */
};
/**
* @brief Open a msatt device
*
* A board is selected by lun, and a handle is returned for further
* reference to it.
*
* @param lun - LUN of msatt card
*
* @return >0 - on success, device file descriptor number
*/
int oau_att_open(int lun);
/**
* @brief close a channel handle
*
* @param fd Handle to close
*/
int oau_att_close(int fd);
/**
* @brief Get attenuation value for a given channel
*
* Each channel can be on one of these states:
* - No attenuation active (Relay value = 0x0)
* - 20dB attenuation (Relay value = 0x1)
* - 40dB attenuation (Relay value = 0x3)
*
* @param fd Device handle identifying board
* @param channel Channel [1,2,3,4] on the board to read from
*
* @return ATT_ERR on failure, another oau_att_value_enum value on success
*/
enum oau_att_value_enum oau_att_get_relay(int fd, int channel);
/**
* @brief Set attenuation value for a given channel
*
* @param fd Device handle identifying board
* @param channel Channel on the board [1,2,3,4]
* @param val Valid oau_att_value_enum relay value
*
* @return Upon successful completion, returns a value other than -1. On failure it returns -1
*/
int oau_att_set_relay(int fd, int channel, enum oau_att_value_enum val);
/**
* @brief Gets the number of channels (2 or 4)
*
* @param fd Device handle identifying board
*
* @return -1 on fail, 2 for MSATTN2 and 4 for MSATTN4
*/
int oau_att_get_nchannels(int fd);
/* libmsatt version string */
extern const char * const liboau_att_version_s;
#ifdef __cplusplus
}
#endif
#endif /* __LIBOASIS_USB_ATT_H */
#include <stdio.h>
#include <unistd.h>
#include "liboasis-usb-att.h"
int main()
{
int fd = oau_att_open(0);
for(;;)
{
fprintf(stderr,".");
oau_att_set_relay ( fd, 4, ATT_1 );
sleep(1);
fprintf(stderr,".");
oau_att_set_relay ( fd, 4, ATT_2 );
sleep(1);
fprintf(stderr,".");
oau_att_set_relay ( fd, 4, ATT_NONE );
sleep(1);
}
oau_att_close(fd);
return 0;
}
\ No newline at end of file
OBJS = oasis-usb-att-test.o
CFLAGS = -I../lib -DGIT_VERSION="dummy"
all: testprog
testprog: $(OBJS)
gcc -o oasis-usb-att-test $(OBJS) -L../lib -loasis-usb-att -lftdi
\ No newline at end of file
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <math.h>
#include <stdlib.h>
#include "liboasis-usb-att.h"
static char git_version[] = "git_version: "; // GIT_VERSION;
int device;
int selected_channel;
int relay_register;
int num_channels;
char relay_bit_string[20];
void uint16_to_bit_string(char *s, uint16_t r)
{
uint16_t bitmask;
int i;
bitmask = (1 << 15);
for (i = 0; i < 19; i++) {
s[i] = ' ';
if (i % 5 == 4)
continue;
s[i] = r & bitmask ? '1' : '0';
bitmask >>= 1;
}
s[i] = 0;
}
int get_dB_at_channel (int chan)
{
int chan_db;
chan_db = 3 << ((chan -1) * 4);
chan_db = (chan_db & relay_register) >> ((chan -1) * 4);
if (chan_db == 1)
chan_db = 20;
else if (chan_db == 3)
chan_db = 40;
return chan_db;
}
void print_menu ()
{
int i;
uint16_to_bit_string(relay_bit_string, relay_register);
// printf("\033[2J"); /* clear the screen */
// printf("\033[H"); /* position cursor at top-left corner */
printf("\n--------------------------------------\n");
printf("| OASIS USB Attenuator |\n");
printf("| Test program |\n");
printf("--------------------------------------\n");
printf("\n----> Selected channel is %d\n", selected_channel);
printf("\n----> Relays command register: %08x = [%s]\n",
relay_register, relay_bit_string);
for (i=1; i<=num_channels;i++) {
printf("\n\tChannel %d: %2d dB ", i, get_dB_at_channel(i));
if (i == selected_channel)
printf("[*]");
}
printf("\n\n [0] - Re-read attenuation values\n");
printf("\n [1] - Change current channel\n");
printf("\n [2] - Set attenuation to 20dB\n");
printf("\n [3] - Set attenuation to 40dB\n");
printf("\n [4] - Unset attenuation\n");
printf("\n [q] - Quit test\n");
printf("\n Choose an option: ");
}
int get_register_value (int fd)
{
int value = 0;
int tmp;
int i;
for (i=1; i<=num_channels; i++) {
tmp = oau_att_get_relay(fd, i);
tmp = tmp << 4 * (i-1);
value |= tmp;
}
return value;
}
void change_channel ()
{
char option;
char ch;
/* Manual flush ?? */
while( (ch = fgetc(stdin)) != EOF && ch != '\n' ){}
printf("\nEnter new channel [1-4]: ");
scanf("%c",&option);
if ((option >= '1') && (option <= '4')) {
selected_channel = atoi(&option);
} else {
printf("Invalid channel\n");
}
}
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s\n", liboau_att_version_s);
}
int main (int argc, char *argv[])
{
int fd;
char option;
selected_channel = 1;
if (argc != 2)
{
printf("Insufficient number of arguments\n");
printf("\nPlease use: %s <lun_of_the_device>\n", argv[0]);
printf("or: %s -v for version info\n", argv[0]);
exit(-1);
}
if(!strcmp("-v", argv[1])) {
print_version(argv[0]);
exit(0);
}
else
{
device = atoi(argv[1]);
}
if ((fd = oau_att_open(device)) < 0) {
perror ("open failed\n");
return -1;
}
/* Check for channel count*/
num_channels = oau_att_get_nchannels(fd);
if (num_channels < 0) {
printf("Can not get channel count. Exiting...\n");
return -1;
}
do {
relay_register = get_register_value(fd);
print_menu();
scanf("%c", &option);
switch (option) {
case '0':
break;
case '1':
change_channel();
break;
case '2':
oau_att_set_relay(fd, selected_channel, ATT_1);
break;
case '3':
oau_att_set_relay(fd, selected_channel, ATT_2);
break;
case '4':
oau_att_set_relay(fd, selected_channel, ATT_NONE);
break;
default:
if ((option != 'q') && (option != 'Q'))
printf("Unknown option\n");
break;
}
} while ((option != 'q') && (option != 'Q'));
/* That's all folks! */
oau_att_close(fd);
return 1;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment