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); 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)
{ {

View File

@ -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 */