rfdsatt: Move to 1-based channel and stage numbers
This matches more with how SCPI controlled attenuators work
This commit is contained in:
parent
dfb3294ac8
commit
3cfd61baa7
|
@ -43,9 +43,40 @@ static void gpio_pulse_clk(void)
|
||||||
gpio_pulse(g_att_cfg->gpio_clock.bank, g_att_cfg->gpio_clock.gpio_nr);
|
gpio_pulse(g_att_cfg->gpio_clock.bank, g_att_cfg->gpio_clock.gpio_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* validate if a channel number is within the permitted range */
|
||||||
|
static bool chan_is_valid(uint8_t channel)
|
||||||
|
{
|
||||||
|
if (channel == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (channel > g_att_cfg->num_channels)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate if a stage number is within the permitted range */
|
||||||
|
static bool stage_is_valid(uint8_t channel, uint8_t stage)
|
||||||
|
{
|
||||||
|
if (!chan_is_valid(channel))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (stage == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (stage > g_att_cfg->channels[channel-1].num_stages)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* internal low-level helper */
|
||||||
static void _attenuator_stage_set(uint8_t channel, uint8_t stage, uint8_t val_qdb)
|
static void _attenuator_stage_set(uint8_t channel, uint8_t stage, uint8_t val_qdb)
|
||||||
{
|
{
|
||||||
const struct attenuator_def *ad = &g_att_cfg->channels[channel].stage[stage];
|
/* we assume the [internal] caller has verified those */
|
||||||
|
uint8_t chan_idx = channel-1;
|
||||||
|
uint8_t stage_idx = stage-1;
|
||||||
|
const struct attenuator_def *ad = &g_att_cfg->channels[chan_idx].stage[stage_idx];
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -67,13 +98,13 @@ static void _attenuator_stage_set(uint8_t channel, uint8_t stage, uint8_t val_qd
|
||||||
gpio_pulse(ad->le.bank, ad->le.gpio_nr);
|
gpio_pulse(ad->le.bank, ad->le.gpio_nr);
|
||||||
|
|
||||||
/* actual value we have set may not be exactly what was requested */
|
/* actual value we have set may not be exactly what was requested */
|
||||||
g_att_state[channel][stage].value_qdB.current = val_qdb;
|
g_att_state[chan_idx][stage_idx].value_qdB.current = val_qdb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set a given attenuator to a given value
|
/*! set a given attenuator to a given value
|
||||||
* \param channel The RF channel (0..7)
|
* \param channel The RF channel (1..8)
|
||||||
* \param stage Attenuator stage (0..1)
|
* \param stage Attenuator stage (1..2)
|
||||||
* \param value in quarter-dB (0..124)
|
* \param val_qdb in quarter-dB (0..124)
|
||||||
*/
|
*/
|
||||||
int attenuator_stage_set(uint8_t channel, uint8_t stage, uint8_t val_qdb)
|
int attenuator_stage_set(uint8_t channel, uint8_t stage, uint8_t val_qdb)
|
||||||
{
|
{
|
||||||
|
@ -82,10 +113,7 @@ int attenuator_stage_set(uint8_t channel, uint8_t stage, uint8_t val_qdb)
|
||||||
if (!g_att_cfg)
|
if (!g_att_cfg)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (channel >= g_att_cfg->num_channels)
|
if (!stage_is_valid(channel, stage))
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (stage >= g_att_cfg->channels[channel].num_stages)
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (val > 0x1f)
|
if (val > 0x1f)
|
||||||
|
@ -98,29 +126,37 @@ int attenuator_stage_set(uint8_t channel, uint8_t stage, uint8_t val_qdb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get current attenuator value in quarter-dB */
|
/*! get current attenuator value in quarter-dB
|
||||||
|
* \param channel The RF channel (1..8)
|
||||||
|
* \param stage Attenuator stage (1..2)
|
||||||
|
*/
|
||||||
int attenuator_stage_get(uint8_t channel, uint8_t stage, enum attenuator_value av)
|
int attenuator_stage_get(uint8_t channel, uint8_t stage, enum attenuator_value av)
|
||||||
{
|
{
|
||||||
|
uint8_t chan_idx;
|
||||||
|
uint8_t stage_idx;
|
||||||
|
|
||||||
if (!g_att_cfg)
|
if (!g_att_cfg)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (channel >= g_att_cfg->num_channels)
|
if (!stage_is_valid(channel, stage))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (stage >= g_att_cfg->channels[channel].num_stages)
|
chan_idx = channel - 1;
|
||||||
return -ENODEV;
|
stage_idx = stage - 1;
|
||||||
|
|
||||||
switch (av) {
|
switch (av) {
|
||||||
case ATT_VAL_CURRENT:
|
case ATT_VAL_CURRENT:
|
||||||
return g_att_state[channel][stage].value_qdB.current;
|
return g_att_state[chan_idx][stage_idx].value_qdB.current;
|
||||||
case ATT_VAL_STARTUP:
|
case ATT_VAL_STARTUP:
|
||||||
return g_att_state[channel][stage].value_qdB.startup;
|
return g_att_state[chan_idx][stage_idx].value_qdB.startup;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set an overall attenuation value for an entire channel */
|
/*! set an overall attenuation value for an entire channel (combination of stages)
|
||||||
|
* \param channel The RF channel (1..8)
|
||||||
|
* \param val_qdb Attenuation in quarter-dB (0..124) */
|
||||||
int attenuator_chan_set(uint8_t channel, uint8_t val_qdb, bool split_equal)
|
int attenuator_chan_set(uint8_t channel, uint8_t val_qdb, bool split_equal)
|
||||||
{
|
{
|
||||||
uint8_t val_a, val_b;
|
uint8_t val_a, val_b;
|
||||||
|
@ -128,7 +164,7 @@ int attenuator_chan_set(uint8_t channel, uint8_t val_qdb, bool split_equal)
|
||||||
if (!g_att_cfg)
|
if (!g_att_cfg)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (channel >= g_att_cfg->num_channels)
|
if (!chan_is_valid(channel))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (val_qdb/4 > 0x3f)
|
if (val_qdb/4 > 0x3f)
|
||||||
|
@ -148,25 +184,29 @@ int attenuator_chan_set(uint8_t channel, uint8_t val_qdb, bool split_equal)
|
||||||
|
|
||||||
printf("Setting CH%u to %02u + %02u = %03u dB\r\n", channel, val_a/4, val_b/4, val_qdb/4);
|
printf("Setting CH%u to %02u + %02u = %03u dB\r\n", channel, val_a/4, val_b/4, val_qdb/4);
|
||||||
|
|
||||||
_attenuator_stage_set(channel, 0, val_a);
|
_attenuator_stage_set(channel, 1, val_a);
|
||||||
_attenuator_stage_set(channel, 1, val_b);
|
_attenuator_stage_set(channel, 2, val_b);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the cumulative attenuation of all stages within one channel */
|
/*! get the cumulative attenuation of all stages within one channel
|
||||||
|
* \param channel The RF channel (1..8) */
|
||||||
int attenuator_chan_get(uint8_t channel, enum attenuator_value av)
|
int attenuator_chan_get(uint8_t channel, enum attenuator_value av)
|
||||||
{
|
{
|
||||||
|
uint8_t chan_idx;
|
||||||
uint8_t stage;
|
uint8_t stage;
|
||||||
int res;
|
int res = 0;
|
||||||
|
|
||||||
if (!g_att_cfg)
|
if (!g_att_cfg)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (channel >= g_att_cfg->num_channels)
|
if (!chan_is_valid(channel))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
for (stage = 0; stage < g_att_cfg->channels[channel].num_stages; stage++) {
|
chan_idx = channel-1;
|
||||||
|
|
||||||
|
for (stage = 1; stage <= g_att_cfg->channels[chan_idx].num_stages; stage++) {
|
||||||
int rc = attenuator_stage_get(channel, stage, av);
|
int rc = attenuator_stage_get(channel, stage, av);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -176,7 +216,7 @@ int attenuator_chan_get(uint8_t channel, enum attenuator_value av)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the attenuator driver */
|
/*! initialize the attenuator driver */
|
||||||
void attenuator_init(const struct attenuator_cfg *cfg,
|
void attenuator_init(const struct attenuator_cfg *cfg,
|
||||||
struct attenuator_state **state)
|
struct attenuator_state **state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -183,14 +183,14 @@ DEFUN(att_show, att_show_cmd, "show", "Show state of all attenuators")
|
||||||
{
|
{
|
||||||
unsigned int channel;
|
unsigned int channel;
|
||||||
|
|
||||||
for (channel = 0; channel < board_att_cfg.num_channels; channel++) {
|
for (channel = 1; channel <= board_att_cfg.num_channels; channel++) {
|
||||||
unsigned int stage;
|
unsigned int stage_idx;
|
||||||
int stage_qdb[2];
|
int stage_qdb[2];
|
||||||
int sum_qdb = 0;
|
int sum_qdb = 0;
|
||||||
|
|
||||||
for (stage = 0; stage < ARRAY_SIZE(stage_qdb); stage++) {
|
for (stage_idx = 0; stage_idx < ARRAY_SIZE(stage_qdb); stage_idx++) {
|
||||||
stage_qdb[stage] = attenuator_stage_get(channel, stage, ATT_VAL_CURRENT);
|
stage_qdb[stage_idx] = attenuator_stage_get(channel, stage_idx+1, ATT_VAL_CURRENT);
|
||||||
sum_qdb += stage_qdb[stage];
|
sum_qdb += stage_qdb[stage_idx];
|
||||||
}
|
}
|
||||||
printf("Channel %02u: Stage1 %02d dB, Stage2 %02d dB, Sum %02d dB\r\n",
|
printf("Channel %02u: Stage1 %02d dB, Stage2 %02d dB, Sum %02d dB\r\n",
|
||||||
channel, stage_qdb[0]/4, stage_qdb[1]/4, sum_qdb/4);
|
channel, stage_qdb[0]/4, stage_qdb[1]/4, sum_qdb/4);
|
||||||
|
@ -203,26 +203,36 @@ DEFUN(att_set, att_set_cmd, "set",
|
||||||
int channel, stage, dB;
|
int channel, stage, dB;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc < 3 || argc > 4) {
|
||||||
printf("You muts specify three arguments (channel, stage, db)\r\n");
|
printf("You must specify two (channel, dB) or three arguments (channel, stage, db)\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
switch (argc) {
|
||||||
|
case 3:
|
||||||
|
channel = atoi(argv[1]);
|
||||||
|
dB = atoi(argv[2]);
|
||||||
|
rc = attenuator_chan_set(channel, dB*4, true);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
channel = atoi(argv[1]);
|
channel = atoi(argv[1]);
|
||||||
stage = atoi(argv[2]);
|
stage = atoi(argv[2]);
|
||||||
dB = atoi(argv[3]);
|
dB = atoi(argv[3]);
|
||||||
|
|
||||||
printf("Setting attenuator channel %d stage %d to %d dB...\r\n", channel, stage, dB);
|
|
||||||
|
|
||||||
rc = attenuator_stage_set(channel, stage, dB*4);
|
rc = attenuator_stage_set(channel, stage, dB*4);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("You must specify two (channel, dB) or three arguments (channel, stage, db)\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
printf("Error setting attenuator: %d\r\n", rc);
|
printf("Error setting attenuator %d: %d\r\n", channel, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEFUN(interact, interact_cmd, "interact", "Enter interactive single-key mode")
|
DEFUN(interact, interact_cmd, "interact", "Enter interactive single-key mode")
|
||||||
{
|
{
|
||||||
uint8_t g_chan = 0;
|
uint8_t g_chan = 1;
|
||||||
uint8_t g_stage = 0;
|
uint8_t g_stage = 1;
|
||||||
uint8_t g_val = 0;
|
uint8_t g_val = 0;
|
||||||
|
|
||||||
printf("Entering interactive single-key mode. Press 'X' for exit\r\n");
|
printf("Entering interactive single-key mode. Press 'X' for exit\r\n");
|
||||||
|
@ -238,8 +248,8 @@ DEFUN(interact, interact_cmd, "interact", "Enter interactive single-key mode")
|
||||||
case 'X': /* exit */
|
case 'X': /* exit */
|
||||||
return;
|
return;
|
||||||
case '1': case '2': case '3': case '4': /* channel number */
|
case '1': case '2': case '3': case '4': /* channel number */
|
||||||
g_chan = ch - '1';
|
g_chan = ch - '0';
|
||||||
g_stage = 0;
|
g_stage = 1;
|
||||||
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
|
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
|
||||||
break;
|
break;
|
||||||
case '0': /* set to 0dB */
|
case '0': /* set to 0dB */
|
||||||
|
@ -256,15 +266,15 @@ DEFUN(interact, interact_cmd, "interact", "Enter interactive single-key mode")
|
||||||
if (g_val > 0)
|
if (g_val > 0)
|
||||||
g_val--;
|
g_val--;
|
||||||
break;
|
break;
|
||||||
case 'a': /* stage 0 */
|
case 'a': /* stage 1 */
|
||||||
if (g_stage != 0) {
|
if (g_stage != 1) {
|
||||||
g_stage = 0;
|
g_stage = 1;
|
||||||
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
|
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'b': /* stage 1 */
|
case 'b': /* stage 2 */
|
||||||
if (g_stage != 1) {
|
if (g_stage != 2) {
|
||||||
g_stage = 1;
|
g_stage = 2;
|
||||||
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
|
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -277,8 +287,7 @@ DEFUN(interact, interact_cmd, "interact", "Enter interactive single-key mode")
|
||||||
|
|
||||||
DEFUN(test, test_cmd, "test", "Enter interactive test-ramp mode")
|
DEFUN(test, test_cmd, "test", "Enter interactive test-ramp mode")
|
||||||
{
|
{
|
||||||
uint8_t g_chan = 0;
|
uint8_t g_chan = 1;
|
||||||
uint8_t g_stage = 0;
|
|
||||||
uint8_t g_val = 0;
|
uint8_t g_val = 0;
|
||||||
|
|
||||||
printf("Entering interactive test-ramp mode. Press 'X' for exit\r\n");
|
printf("Entering interactive test-ramp mode. Press 'X' for exit\r\n");
|
||||||
|
@ -290,7 +299,7 @@ DEFUN(test, test_cmd, "test", "Enter interactive test-ramp mode")
|
||||||
case 'X': /* exit */
|
case 'X': /* exit */
|
||||||
return;
|
return;
|
||||||
case '1': case '2': case '3': case '4': /* channel number */
|
case '1': case '2': case '3': case '4': /* channel number */
|
||||||
g_chan = ch - '1';
|
g_chan = ch - '0';
|
||||||
g_val = 0;
|
g_val = 0;
|
||||||
break;
|
break;
|
||||||
case '0': /* set to 0dB */
|
case '0': /* set to 0dB */
|
||||||
|
|
Loading…
Reference in New Issue