altos: Make sure we drop the SPI mutex when aborting cc1120 recv
[fw/altos] / src / drivers / ao_cc115l.c
index d9b9a89b7f29649a147203abe06277711a95f367..cf61acfe9c4ae45a6def0d88caf05c8d3d0dac96 100644 (file)
@@ -249,36 +249,81 @@ ao_radio_idle(void)
 }
 
 /*
- * Packet deviation is 20.5kHz
+ * Packet deviation
  *
  *     fdev = fosc >> 17 * (8 + dev_m) << dev_e
  *
+ * For 38400 baud, use 20.5kHz:
+ *
  *             26e6 / (2 ** 17) * (8 + 5) * (2 ** 3) = 20630Hz
+ *
+ * For 9600 baud, use 5.125kHz:
+ *
+ *             26e6 / (2 ** 17) * (8 + 5) * (2 ** 1) = 5157Hz
+ *
+ * For 2400 baud, use 1.5kHz:
+ *
+ *             26e6 / (2 ** 17) * (8 + 0) * (2 ** 0) = 1587Hz
  */
 
-#define PACKET_DEV_E   3
-#define PACKET_DEV_M   5
+#define PACKET_DEV_E_384       3
+#define PACKET_DEV_M_384       5
+
+#define PACKET_DEV_E_96                1
+#define PACKET_DEV_M_96                5
+
+#define PACKET_DEV_E_24                0
+#define PACKET_DEV_M_24                0
 
 /*
- * For our packet data, set the symbol rate to 38400 Baud
+ * For our packet data:
  *
  *              (256 + DATARATE_M) * 2 ** DATARATE_E
  *     Rdata = -------------------------------------- * fosc
  *                          2 ** 28
  *
+ * For 38400 baud:
+ *
  *             (256 + 131) * (2 ** 10) / (2**28) * 26e6 = 38383
  *
  *     DATARATE_M = 131
- *     DATARATE_E = 10
+ *     DATARATE_E_384 = 10
+ *     DATARATE_E_96 = 8
+ *     DATARATE_E_24 = 6
  */
-#define PACKET_DRATE_E 10
-#define PACKET_DRATE_M 131
+#define PACKET_DRATE_M         131
+
+#define PACKET_DRATE_E_384     10
+#define PACKET_DRATE_E_96      8
+#define PACKET_DRATE_E_24      6
+
+static const struct {
+       uint8_t         mdmcfg4;
+       uint8_t         deviatn;
+} packet_rate_setup[] = {
+       [AO_RADIO_RATE_38400] = {
+               .mdmcfg4 = ((0xf << 4) |
+                           (PACKET_DRATE_E_384 << CC115L_MDMCFG4_DRATE_E)),
+               .deviatn = ((PACKET_DEV_E_384 << CC115L_DEVIATN_DEVIATION_E) |
+                           (PACKET_DEV_M_384 << CC115L_DEVIATN_DEVIATION_M)),
+       },
+
+       [AO_RADIO_RATE_9600] = {
+               .mdmcfg4 = ((0xf << 4) |
+                           (PACKET_DRATE_E_96 << CC115L_MDMCFG4_DRATE_E)),
+               .deviatn = ((PACKET_DEV_E_96 << CC115L_DEVIATN_DEVIATION_E) |
+                           (PACKET_DEV_M_96 << CC115L_DEVIATN_DEVIATION_M)),
+       },
+
+       [AO_RADIO_RATE_2400] = {
+               .mdmcfg4 = ((0xf << 4) |
+                           (PACKET_DRATE_E_24 << CC115L_MDMCFG4_DRATE_E)),
+               .deviatn = ((PACKET_DEV_E_24 << CC115L_DEVIATN_DEVIATION_E) |
+                           (PACKET_DEV_M_24 << CC115L_DEVIATN_DEVIATION_M)),
+       },
+};
 
 static const uint16_t packet_setup[] = {
-       CC115L_DEVIATN,         ((PACKET_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
-                                (PACKET_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
-       CC115L_MDMCFG4,         ((0xf << 4) |
-                                (PACKET_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
        CC115L_MDMCFG3,         (PACKET_DRATE_M),
        CC115L_MDMCFG2,         (0x00 |
                                 (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
@@ -403,9 +448,13 @@ ao_radio_set_mode(uint16_t new_mode)
                return;
 
        changes = new_mode & (~ao_radio_mode);
-       if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
+       if (changes & AO_RADIO_MODE_BITS_PACKET_TX) {
+               ao_radio_reg_write(CC115L_MDMCFG4, packet_rate_setup[ao_config.radio_rate].mdmcfg4);
+               ao_radio_reg_write(CC115L_DEVIATN, packet_rate_setup[ao_config.radio_rate].deviatn);
+
                for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
                        ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
+       }
 
        if (changes & AO_RADIO_MODE_BITS_RDF)
                for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
@@ -494,6 +543,7 @@ static void
 ao_radio_get(void)
 {
        static uint32_t last_radio_setting;
+       static uint8_t  last_radio_rate;
 
        ao_mutex_get(&ao_radio_mutex);
        if (!ao_radio_configured)
@@ -504,6 +554,10 @@ ao_radio_get(void)
                ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting);
                last_radio_setting = ao_config.radio_setting;
        }
+       if (ao_config.radio_rate != last_radio_rate) {
+               ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET_TX;
+               last_radio_rate = ao_config.radio_rate;
+       }
 }
 
 static void
@@ -612,6 +666,12 @@ ao_radio_rdf_abort(void)
 
 #define POWER_STEP     0x08
 
+#if HAS_RADIO_POWER
+#define RADIO_POWER    ao_config.radio_power
+#else
+#define RADIO_POWER    0xc0
+#endif
+
 static void
 ao_radio_stx(void)
 {
@@ -619,9 +679,10 @@ ao_radio_stx(void)
        ao_radio_pa_on();
        ao_radio_reg_write(CC115L_PA, 0);
        ao_radio_strobe(CC115L_STX);
-       for (power = POWER_STEP; power < ao_config.radio_power; power += POWER_STEP)
+       for (power = POWER_STEP; power < RADIO_POWER; power += POWER_STEP)
                ao_radio_reg_write(CC115L_PA, power);
-       ao_radio_reg_write(CC115L_PA, ao_config.radio_power);
+       if (power != RADIO_POWER)
+               ao_radio_reg_write(CC115L_PA, RADIO_POWER);
 }
 
 static void