/* * lib/misctxrx.c - Miscellaenous transceiver helper functions * * Written 2010-2011 by Werner Almesberger * Copyright 2010-2011 Werner Almesberger * * 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 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include #include "at86rf230.h" #include "atrf.h" #include "misctxrx.h" /* ----- Interrupts -------------------------------------------------------- */ static volatile int run = 1; static void die(int sig) { run = 0; } uint8_t wait_for_interrupt(struct atrf_dsc *dsc, uint8_t wait_for, uint8_t ignore, int sleep_us, int timeout) { uint8_t irq = 0, show; void (*old_sig)(int); run = 1; old_sig = signal(SIGINT, die); while (run) { while (run && !atrf_interrupt(dsc)) { usleep(sleep_us); if (timeout && !--timeout) { irq = 0; goto out; } } irq = atrf_reg_read(dsc, REG_IRQ_STATUS); if (atrf_error(dsc)) exit(1); if (!irq) continue; show = irq & ~ignore; if (!show) { if (irq & wait_for) break; continue; } fprintf(stderr, "IRQ (0x%02x):", irq); if (irq & IRQ_PLL_LOCK) fprintf(stderr, " PLL_LOCK"); if (irq & IRQ_PLL_UNLOCK) fprintf(stderr, " PLL_UNLOCK"); if (irq & IRQ_RX_START) fprintf(stderr, " RX_START"); if (irq & IRQ_TRX_END) fprintf(stderr, " TRX_END"); if (irq & IRQ_CCA_ED_DONE) fprintf(stderr, " CCA_ED_DONE"); if (irq & IRQ_AMI) fprintf(stderr, " AMI"); if (irq & IRQ_TRX_UR) fprintf(stderr, " TRX_UR"); if (irq & IRQ_BAT_LOW) fprintf(stderr, " BAT_LOW"); fprintf(stderr, "\n"); if (irq & wait_for) break; } out: signal(SIGINT, old_sig); if (!run) raise(SIGINT); return irq; } /* ----- Transmit power ---------------------------------------------------- */ static const double tx_pwr_230[] = { 3.0, 2.6, 2.1, 1.6, 1.1, 0.5, -0.2, -1.2, -2.2, -3.2, -4.2, -5.2, -7.2, -9.2, -12.2, -17.2 }; static const double tx_pwr_231[] = { 3.0, 2.8, 2.3, 1.8, 1.3, 0.7, 0.0, -1, -2, -3, -4, -5, -7, -9, -12, -17 }; #define POWER_TABLE_SIZE (sizeof(tx_pwr_230)/sizeof(*tx_pwr_230)) void set_power_step(struct atrf_dsc *dsc, int power, int crc) { uint8_t tmp; switch (atrf_identify(dsc)) { case artf_at86rf230: atrf_reg_write(dsc, REG_PHY_TX_PWR, (crc ? TX_AUTO_CRC_ON_230 : 0) | power); break; case artf_at86rf231: tmp = atrf_reg_read(dsc, REG_PHY_TX_PWR); tmp = (tmp & ~TX_PWR_MASK) | power; atrf_reg_write(dsc, REG_PHY_TX_PWR, tmp); atrf_reg_write(dsc, REG_TRX_CTRL_1, crc ? TX_AUTO_CRC_ON : 0); break; default: abort(); } } static const double *tx_power_table(struct atrf_dsc *dsc) { switch (atrf_identify(dsc)) { case artf_at86rf230: return tx_pwr_230; case artf_at86rf231: return tx_pwr_231; break; default: abort(); } } int tx_power_dBm2step(struct atrf_dsc *dsc, double power) { const double *tx_pwr = tx_power_table(dsc); int n; for (n = 0; n != POWER_TABLE_SIZE-1; n++) if (tx_pwr[n] <= power) break; return n; } double tx_power_step2dBm(struct atrf_dsc *dsc, int step) { const double *tx_pwr = tx_power_table(dsc); if (step < 0 || step >= POWER_TABLE_SIZE) abort(); return tx_pwr[step]; } void set_power_dBm(struct atrf_dsc *dsc, double power, int crc) { int step; double got; step = tx_power_dBm2step(dsc, power); got = tx_power_step2dBm(dsc, step); if (fabs(got-power) > 0.01) fprintf(stderr, "TX power %.1f dBm\n", got); set_power_step(dsc, step, crc); }