rfdsatt: Move to 1-based channel and stage numbers

This matches more with how SCPI controlled attenuators work
This commit is contained in:
Harald Welte 2021-05-07 09:05:41 +02:00
parent dfb3294ac8
commit 3cfd61baa7
2 changed files with 101 additions and 52 deletions

View File

@ -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);
}
/* 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)
{
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;
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);
/* 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
* \param channel The RF channel (0..7)
* \param stage Attenuator stage (0..1)
* \param value in quarter-dB (0..124)
/*! set a given attenuator to a given value
* \param channel The RF channel (1..8)
* \param stage Attenuator stage (1..2)
* \param val_qdb in quarter-dB (0..124)
*/
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)
return -ENODEV;
if (channel >= g_att_cfg->num_channels)
return -ENODEV;
if (stage >= g_att_cfg->channels[channel].num_stages)
if (!stage_is_valid(channel, stage))
return -ENODEV;
if (val > 0x1f)
@ -98,29 +126,37 @@ int attenuator_stage_set(uint8_t channel, uint8_t stage, uint8_t val_qdb)
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)
{
uint8_t chan_idx;
uint8_t stage_idx;
if (!g_att_cfg)
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;
chan_idx = channel - 1;
stage_idx = stage - 1;
switch (av) {
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:
return g_att_state[channel][stage].value_qdB.startup;
return g_att_state[chan_idx][stage_idx].value_qdB.startup;
default:
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)
{
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)
return -ENODEV;
if (channel >= g_att_cfg->num_channels)
if (!chan_is_valid(channel))
return -ENODEV;
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);
_attenuator_stage_set(channel, 0, val_a);
_attenuator_stage_set(channel, 1, val_b);
_attenuator_stage_set(channel, 1, val_a);
_attenuator_stage_set(channel, 2, val_b);
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)
{
uint8_t chan_idx;
uint8_t stage;
int res;
int res = 0;
if (!g_att_cfg)
return -ENODEV;
if (channel >= g_att_cfg->num_channels)
if (!chan_is_valid(channel))
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);
if (rc < 0)
return rc;
@ -176,7 +216,7 @@ int attenuator_chan_get(uint8_t channel, enum attenuator_value av)
return res;
}
/* initialize the attenuator driver */
/*! initialize the attenuator driver */
void attenuator_init(const struct attenuator_cfg *cfg,
struct attenuator_state **state)
{

View File

@ -183,14 +183,14 @@ DEFUN(att_show, att_show_cmd, "show", "Show state of all attenuators")
{
unsigned int channel;
for (channel = 0; channel < board_att_cfg.num_channels; channel++) {
unsigned int stage;
for (channel = 1; channel <= board_att_cfg.num_channels; channel++) {
unsigned int stage_idx;
int stage_qdb[2];
int sum_qdb = 0;
for (stage = 0; stage < ARRAY_SIZE(stage_qdb); stage++) {
stage_qdb[stage] = attenuator_stage_get(channel, stage, ATT_VAL_CURRENT);
sum_qdb += stage_qdb[stage];
for (stage_idx = 0; stage_idx < ARRAY_SIZE(stage_qdb); stage_idx++) {
stage_qdb[stage_idx] = attenuator_stage_get(channel, stage_idx+1, ATT_VAL_CURRENT);
sum_qdb += stage_qdb[stage_idx];
}
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);
@ -203,26 +203,36 @@ DEFUN(att_set, att_set_cmd, "set",
int channel, stage, dB;
int rc;
if (argc < 3) {
printf("You muts specify three arguments (channel, stage, db)\r\n");
if (argc < 3 || argc > 4) {
printf("You must specify two (channel, dB) or three arguments (channel, stage, db)\r\n");
return;
}
channel = atoi(argv[1]);
stage = atoi(argv[2]);
dB = atoi(argv[3]);
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]);
stage = atoi(argv[2]);
dB = atoi(argv[3]);
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;
}
printf("Setting attenuator channel %d stage %d to %d dB...\r\n", channel, stage, dB);
rc = attenuator_stage_set(channel, stage, dB*4);
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")
{
uint8_t g_chan = 0;
uint8_t g_stage = 0;
uint8_t g_chan = 1;
uint8_t g_stage = 1;
uint8_t g_val = 0;
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 */
return;
case '1': case '2': case '3': case '4': /* channel number */
g_chan = ch - '1';
g_stage = 0;
g_chan = ch - '0';
g_stage = 1;
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
break;
case '0': /* set to 0dB */
@ -256,15 +266,15 @@ DEFUN(interact, interact_cmd, "interact", "Enter interactive single-key mode")
if (g_val > 0)
g_val--;
break;
case 'a': /* stage 0 */
if (g_stage != 0) {
g_stage = 0;
case 'a': /* stage 1 */
if (g_stage != 1) {
g_stage = 1;
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
}
break;
case 'b': /* stage 1 */
if (g_stage != 1) {
g_stage = 1;
case 'b': /* stage 2 */
if (g_stage != 2) {
g_stage = 2;
g_val = attenuator_stage_get(g_chan, g_stage, ATT_VAL_CURRENT);
}
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")
{
uint8_t g_chan = 0;
uint8_t g_stage = 0;
uint8_t g_chan = 1;
uint8_t g_val = 0;
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 */
return;
case '1': case '2': case '3': case '4': /* channel number */
g_chan = ch - '1';
g_chan = ch - '0';
g_val = 0;
break;
case '0': /* set to 0dB */