Commit bfe5bb85 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

dev: added support for '595 shift register and RF switch control

parent cd847743
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include "board.h"
#include "dev/gpio.h"
struct x595_gpio_priv_data
{
struct gpio_pin *pin_rclk;
struct gpio_pin *pin_srclk;
struct gpio_pin *pin_srclr_n;
struct gpio_pin *pin_ser;
int n_regs;
uint32_t cur_data;
};
static int x595_gpio_in(const struct gpio_pin *pin)
{
struct x595_gpio_priv_data *priv = (struct x595_gpio_priv_data *)pin->device->priv;
return priv->cur_data & (1 << pin->pin) ? 1 : 0;
}
static void x595_gpio_sync_out(const struct x595_gpio_priv_data *priv)
{
int i, nbits = priv->n_regs * 8;
gen_gpio_out(priv->pin_srclr_n, 0); // reset the shift register
gen_gpio_out(priv->pin_srclr_n, 1);
for(i = 0; i < nbits; i++)
{
gen_gpio_out(priv->pin_ser, (priv->cur_data & (1 << (nbits - 1 - i))) ? 1 : 0); // shift out the bit
gen_gpio_out(priv->pin_srclk, 0); // pulse the serial clock
gen_gpio_out(priv->pin_srclk, 1);
gen_gpio_out(priv->pin_srclk, 0);
}
gen_gpio_out(priv->pin_rclk, 1); // pass the shift reg contents to the output latch
gen_gpio_out(priv->pin_rclk, 0);
}
static struct x595_gpio_priv_data x595_gpio_priv;
static void x595_gpio_out(const struct gpio_pin *pin, int value)
{
struct x595_gpio_priv_data *priv = (struct x595_gpio_priv_data *)pin->device->priv;
if (value)
priv->cur_data |= (1 << pin->pin);
else
priv->cur_data &= ~(1 << pin->pin);
x595_gpio_sync_out( priv );
}
int x595_gpio_create(struct gpio_device *device, int n_regs, struct gpio_pin *pin_rclk, struct gpio_pin *pin_srclk, struct gpio_pin *pin_srclr_n, struct gpio_pin *pin_ser)
{
device->priv = (void *) &x595_gpio_priv;
x595_gpio_priv.pin_rclk = pin_rclk;
x595_gpio_priv.pin_srclk = pin_srclk;
x595_gpio_priv.pin_srclr_n = pin_srclr_n;
x595_gpio_priv.pin_ser = pin_ser;
x595_gpio_priv.cur_data = 0;
x595_gpio_priv.n_regs = n_regs;
gen_gpio_out(x595_gpio_priv.pin_rclk, 0); // reset the shift register
gen_gpio_out(x595_gpio_priv.pin_srclk, 0); // reset the shift register
gen_gpio_out(x595_gpio_priv.pin_srclr_n, 0); // reset the shift register
usleep(1);
gen_gpio_out(x595_gpio_priv.pin_srclr_n, 1);
x595_gpio_sync_out(&x595_gpio_priv);
device->set_dir = NULL;
device->set_out = x595_gpio_out;
device->read_pin = x595_gpio_in;
return device;
};
\ No newline at end of file
......@@ -19,7 +19,10 @@ obj-$(CONFIG_EMBEDDED_NODE) += \
dev/ad9910.o \
dev/ltc6950.o \
dev/phy_calibration.o \
dev/clock_monitor.o
dev/clock_monitor.o \
dev/74x595.o \
dev/ertm15_rf_switches.o
obj-$(CONFIG_WR_NODE) += \
dev/temperature.o \
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdint.h>
#include "board.h"
#include "dev/gpio.h"
#include "dev/74x595.h"
extern struct gpio_device gpio_aux;
static const struct gpio_pin pin_lo_ctrl_ser = { &gpio_aux, 39 };
static const struct gpio_pin pin_lo_ctrl_updtclk = { &gpio_aux, 40 };
static const struct gpio_pin pin_lo_ctrl_shftclk = { &gpio_aux, 41 };
static const struct gpio_pin pin_ref_ctrl_ser = { &gpio_aux, 42 };
static const struct gpio_pin pin_ref_ctrl_updtclk = { &gpio_aux, 43 };
static const struct gpio_pin pin_ref_ctrl_shftclk = { &gpio_aux, 44 };
static struct gpio_device gpio_rfsw_ref;
// fixme: more than one GPIO chain using '595 register requires dynamic allocator for private data
//static struct gpio_device gpio_rfsw_lo;
#define ERTM15_RF_OUT_ON 0
#define ERTM15_RF_OUT_MONITOR 1
#define ERTM15_RF_OUT_OFF 2
#define ERTM15_RF_LO 0
#define ERTM15_RF_REF 1
// mapping between x595 shift reg (IC26..28 on eRTM15 and the RF switch control pins)
// fixme: pin definitions for LO path
static const struct pin_mapping
{
uint8_t path;
uint8_t channel;
uint8_t distr_channel;
uint8_t ctrl1, ctrl2;
} rf_switch_sreg_pin_mapping[] = {
{ERTM15_RF_REF, 5, 4, 8 + 6, 8 + 7}, // RF5
{ERTM15_RF_REF, 4, 5, 8 + 5, 8 + 4}, // RF4
{ERTM15_RF_REF, 7, 7, 8 + 3, 8 + 2}, // RF5
{ERTM15_RF_REF, 6, 6, 8 + 1, 8 + 0}, // RF5
{ERTM15_RF_REF, 10,12, 16 + 7, 16 + 6}, // RF12
{ERTM15_RF_REF, 9, 9, 6, 7}, // RF9
{ERTM15_RF_REF, 8, 8, 4, 5}, // RF8
{ERTM15_RF_REF, 11,11, 2, 3}, // RF11
{ERTM15_RF_REF, 12,10, 0, 1}, // RF10
{ERTM15_RF_REF, 0, 0, 0, 0}};
static struct pin_mapping* find_pins_for_channel ( int path, int channel )
{
int i;
for(i=0; rf_switch_sreg_pin_mapping[i].channel !=0; i++ )
{
if( rf_switch_sreg_pin_mapping[i].channel == channel && rf_switch_sreg_pin_mapping[i].path == path )
{
return &rf_switch_sreg_pin_mapping[i];
}
}
return NULL;
}
int ertm15_rf_switch_set( int path, int channel, int state)
{
struct gpio_device *gpio = ( path == ERTM15_RF_REF ? &gpio_rfsw_ref : &gpio_rfsw_ref); // fixme
struct pin_mapping *pins = find_pins_for_channel( path, channel );
struct gpio_pin ctrl1, ctrl2;
ctrl1.device = gpio;
ctrl1.pin = pins->ctrl1;
ctrl2.device = gpio;
ctrl2.pin = pins->ctrl2;
if(!pins)
return -1;
// HSWA2-30DR+ I/O CTRL pins function:
// CTRL1 = 0, CTRL2 = 0: OFF
// CTRL1 = 0, CTRL2 = 1: MONITOR
// CTRL1 = 1, CTRL2 = 0: ON
switch(state)
{
case ERTM15_RF_OUT_ON:
gen_gpio_out( &ctrl1, 1 );
gen_gpio_out( &ctrl2, 0 );
break;
case ERTM15_RF_OUT_MONITOR:
gen_gpio_out( &ctrl1, 0 );
gen_gpio_out( &ctrl2, 1 );
break;
case ERTM15_RF_OUT_OFF:
gen_gpio_out( &ctrl1, 0 );
gen_gpio_out( &ctrl2, 0 );
break;
}
return 0;
}
int ertm15_rf_switch_get( int path, int channel )
{
}
void ertm15_rf_switches_init()
{
int i;
x595_gpio_create ( &gpio_rfsw_ref, 3, &pin_ref_ctrl_updtclk, &pin_ref_ctrl_shftclk, NULL, &pin_ref_ctrl_ser );
// disable all RF outputs to the backplane
for( i = 0; rf_switch_sreg_pin_mapping[i].channel != 0; i++ )
{
struct pin_mapping* p = &rf_switch_sreg_pin_mapping[i];
ertm15_rf_switch_set( p->path, p->channel, ERTM15_RF_OUT_OFF );
}
}
......@@ -77,23 +77,31 @@ int wb_gpio_create( struct gpio_device *device, uint32_t base_addr )
void gen_gpio_set_dir(const struct gpio_pin *pin, int dir)
{
if(!pin)
if (!pin)
return;
pin->device->set_dir(pin, dir);
if (!pin->device->set_dir)
return;
pin->device->set_dir(pin, dir);
}
void gen_gpio_out(const struct gpio_pin *pin, int value)
{
if(!pin)
if (!pin)
return;
if (!pin->device->set_out)
return;
pin->device->set_out(pin, value);
pin->device->set_out(pin, value);
}
int gen_gpio_in(const struct gpio_pin *pin)
{
if(!pin)
if (!pin)
return 0;
return pin->device->read_pin(pin);
if (!pin->device->read_pin)
return 0;
return pin->device->read_pin(pin);
}
void gen_gpio_bang(const struct gpio_pin *pin, int count)
......
......@@ -179,6 +179,7 @@ bb_spi_create( &spi_ad9910_lo,
usleep(1000000);
ad9910_program(&dds_ad9910_ref, 0, 0, 0);
ertm15_rf_switches_init();
#if 0
for(;;)
{
......
#ifndef __SN74x595_H
#define __SN74x595_H
int x595_gpio_create(struct gpio_device *device, int n_regs, struct gpio_pin *pin_rclk, struct gpio_pin *pin_srclk, struct gpio_pin *pin_srclr_n, struct gpio_pin *pin_ser);
#endif
......@@ -78,6 +78,7 @@ static void wrc_initialize(void)
pp_printf("WR Core: starting up...\n");
timer_init(1);
usleep_init();
ertm14_init();
......@@ -121,7 +122,6 @@ static void wrc_initialize(void)
/* try reading t24 phase transition from EEPROM */
calib_t24p(WRC_MODE_MASTER, &cal_phase_transition);
spll_very_init();
usleep_init();
shell_init();
wrc_ui_mode = UI_SHELL_MODE;
......
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