Alarm generator, transmitter side

Dependencies:   sx12xx_hal

radio chip selection

Radio chip driver is not included, allowing choice of radio device.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
if you're using SX1280, then import sx1280 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.

This is transmitter project; Receiver side is Alarm Slave project.
This project generates alarm (transmits) from grounding certain pins.
To find the actual pins used, refer to the code where pin[A-D] is declared as DigitalIn.

Alarm message is sent N times with future timestamp indicating when alarm is to occur. This accommodates dropped packets, resulting in alarm occurring when as few as 1 packet is received.

Committer:
dudmuck
Date:
Mon Jan 29 18:20:10 2018 +0000
Revision:
4:19056d9707ef
Parent:
3:d8b57eca8c45
Child:
5:1652e04809fb
set OCP for +20dBm out

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:cb38da4f4b04 1 #include "sx127x_lora.h"
dudmuck 0:cb38da4f4b04 2
dudmuck 3:d8b57eca8c45 3 #ifdef TARGET_DISCO_L072CZ_LRWAN1
dudmuck 3:d8b57eca8c45 4
dudmuck 3:d8b57eca8c45 5 SPI spi(PA_7, PA_6, PB_3); // mosi, miso, sclk
dudmuck 3:d8b57eca8c45 6 // dio0, dio1, nss, spi, rst
dudmuck 3:d8b57eca8c45 7 SX127x radio(PB_4, PB_1, PA_15, spi, PC_0);
dudmuck 3:d8b57eca8c45 8
dudmuck 3:d8b57eca8c45 9 #define CRF1 PA_1
dudmuck 3:d8b57eca8c45 10 #define CRF2 PC_2
dudmuck 3:d8b57eca8c45 11 #define CRF3 PC_1
dudmuck 3:d8b57eca8c45 12 DigitalOut Vctl1(CRF1);
dudmuck 3:d8b57eca8c45 13 DigitalOut Vctl2(CRF2);
dudmuck 3:d8b57eca8c45 14 DigitalOut Vctl3(CRF3);
dudmuck 3:d8b57eca8c45 15
dudmuck 3:d8b57eca8c45 16 void rfsw_callback()
dudmuck 3:d8b57eca8c45 17 {
dudmuck 3:d8b57eca8c45 18 if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER) {
dudmuck 3:d8b57eca8c45 19 Vctl1 = 0;
dudmuck 3:d8b57eca8c45 20 if (radio.RegPaConfig.bits.PaSelect) {
dudmuck 3:d8b57eca8c45 21 Vctl2 = 0;
dudmuck 3:d8b57eca8c45 22 Vctl3 = 1;
dudmuck 3:d8b57eca8c45 23 } else {
dudmuck 3:d8b57eca8c45 24 Vctl2 = 1;
dudmuck 3:d8b57eca8c45 25 Vctl3 = 0;
dudmuck 3:d8b57eca8c45 26 }
dudmuck 3:d8b57eca8c45 27 } else {
dudmuck 3:d8b57eca8c45 28 if (radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER || radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER_SINGLE)
dudmuck 3:d8b57eca8c45 29 Vctl1 = 1;
dudmuck 3:d8b57eca8c45 30 else
dudmuck 3:d8b57eca8c45 31 Vctl1 = 0;
dudmuck 3:d8b57eca8c45 32
dudmuck 3:d8b57eca8c45 33 Vctl2 = 0;
dudmuck 3:d8b57eca8c45 34 Vctl3 = 0;
dudmuck 3:d8b57eca8c45 35 }
dudmuck 3:d8b57eca8c45 36 }
dudmuck 3:d8b57eca8c45 37
dudmuck 3:d8b57eca8c45 38 DigitalIn pinA(PB_12);
dudmuck 3:d8b57eca8c45 39 DigitalIn pinB(PB_13);
dudmuck 3:d8b57eca8c45 40 DigitalIn pinC(PB_14);
dudmuck 3:d8b57eca8c45 41 DigitalIn pinD(PB_15);
dudmuck 3:d8b57eca8c45 42 #else
dudmuck 3:d8b57eca8c45 43 SPI spi(D11, D12, D13); // mosi, miso, sclk
dudmuck 3:d8b57eca8c45 44 // dio0, dio1, nss, spi, rst
dudmuck 3:d8b57eca8c45 45 SX127x radio( D2, D3, D10, spi, A0); // sx1276 arduino shield
dudmuck 3:d8b57eca8c45 46
dudmuck 3:d8b57eca8c45 47 DigitalInOut rfsw(A4); // for SX1276 arduino shield
dudmuck 3:d8b57eca8c45 48
dudmuck 3:d8b57eca8c45 49 void rfsw_callback()
dudmuck 3:d8b57eca8c45 50 {
dudmuck 3:d8b57eca8c45 51 if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER) {
dudmuck 3:d8b57eca8c45 52 rfsw = 1;
dudmuck 3:d8b57eca8c45 53 } else {
dudmuck 3:d8b57eca8c45 54 rfsw = 0;
dudmuck 3:d8b57eca8c45 55 }
dudmuck 0:cb38da4f4b04 56 }
dudmuck 3:d8b57eca8c45 57
dudmuck 3:d8b57eca8c45 58 DigitalIn pinA(PC_3);
dudmuck 3:d8b57eca8c45 59 DigitalIn pinB(PC_2);
dudmuck 3:d8b57eca8c45 60 DigitalIn pinC(PC_6);
dudmuck 3:d8b57eca8c45 61 DigitalIn pinD(PC_8);
dudmuck 3:d8b57eca8c45 62 #endif /* !TARGET_DISCO_L072CZ_LRWAN1 */
dudmuck 3:d8b57eca8c45 63
dudmuck 0:cb38da4f4b04 64 /**********************************************************************/
dudmuck 0:cb38da4f4b04 65
dudmuck 3:d8b57eca8c45 66 SX127x_lora lora(radio);
dudmuck 0:cb38da4f4b04 67 Timer t;
dudmuck 3:d8b57eca8c45 68 #define CMD_PINA 0x02
dudmuck 3:d8b57eca8c45 69 #define CMD_PINB 0x03
dudmuck 3:d8b57eca8c45 70 #define CMD_PINC 0x06
dudmuck 3:d8b57eca8c45 71 #define CMD_PIND 0x08
dudmuck 0:cb38da4f4b04 72
dudmuck 0:cb38da4f4b04 73 static uint16_t crc_ccitt( uint8_t *buffer, uint16_t length )
dudmuck 0:cb38da4f4b04 74 {
dudmuck 0:cb38da4f4b04 75 // The CRC calculation follows CCITT
dudmuck 0:cb38da4f4b04 76 const uint16_t polynom = 0x1021;
dudmuck 0:cb38da4f4b04 77 // CRC initial value
dudmuck 0:cb38da4f4b04 78 uint16_t crc = 0x0000;
dudmuck 0:cb38da4f4b04 79
dudmuck 0:cb38da4f4b04 80 if( buffer == NULL )
dudmuck 0:cb38da4f4b04 81 {
dudmuck 0:cb38da4f4b04 82 return 0;
dudmuck 0:cb38da4f4b04 83 }
dudmuck 0:cb38da4f4b04 84
dudmuck 0:cb38da4f4b04 85 for( uint16_t i = 0; i < length; ++i )
dudmuck 0:cb38da4f4b04 86 {
dudmuck 0:cb38da4f4b04 87 crc ^= ( uint16_t ) buffer[i] << 8;
dudmuck 0:cb38da4f4b04 88 for( uint16_t j = 0; j < 8; ++j )
dudmuck 0:cb38da4f4b04 89 {
dudmuck 0:cb38da4f4b04 90 crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 );
dudmuck 0:cb38da4f4b04 91 }
dudmuck 0:cb38da4f4b04 92 }
dudmuck 0:cb38da4f4b04 93
dudmuck 0:cb38da4f4b04 94 return crc;
dudmuck 0:cb38da4f4b04 95 }
dudmuck 0:cb38da4f4b04 96
dudmuck 1:3199506bc2e5 97 void transmit(unsigned target, uint8_t cmd)
dudmuck 0:cb38da4f4b04 98 {
dudmuck 0:cb38da4f4b04 99 unsigned t_diff;
dudmuck 0:cb38da4f4b04 100 uint16_t crc;
dudmuck 0:cb38da4f4b04 101
dudmuck 1:3199506bc2e5 102 radio.tx_buf[0] = cmd;
dudmuck 0:cb38da4f4b04 103 t_diff = target - t.read_us();
dudmuck 0:cb38da4f4b04 104 radio.tx_buf[1] = t_diff >> 24;
dudmuck 0:cb38da4f4b04 105 radio.tx_buf[2] = t_diff >> 16;
dudmuck 0:cb38da4f4b04 106 radio.tx_buf[3] = t_diff >> 8;
dudmuck 0:cb38da4f4b04 107 radio.tx_buf[4] = t_diff & 0xff;
dudmuck 0:cb38da4f4b04 108 crc = crc_ccitt(radio.tx_buf, 5);
dudmuck 0:cb38da4f4b04 109 radio.tx_buf[5] = crc >> 8;
dudmuck 0:cb38da4f4b04 110 radio.tx_buf[6] = crc & 0xff;
dudmuck 0:cb38da4f4b04 111
dudmuck 0:cb38da4f4b04 112
dudmuck 0:cb38da4f4b04 113 lora.start_tx(lora.RegPayloadLength); /* begin transmission */
dudmuck 0:cb38da4f4b04 114
dudmuck 1:3199506bc2e5 115 while (lora.service() != SERVICE_TX_DONE) { /* wait for transmission to complete */
dudmuck 1:3199506bc2e5 116 }
dudmuck 0:cb38da4f4b04 117
dudmuck 0:cb38da4f4b04 118 printf("t_diff:%u crc:%04x\r\n", t_diff, crc);
dudmuck 0:cb38da4f4b04 119 }
dudmuck 0:cb38da4f4b04 120
dudmuck 0:cb38da4f4b04 121 #define TARGET_LATENCY 2000000
dudmuck 1:3199506bc2e5 122 void send_alarm(uint8_t cmd)
dudmuck 0:cb38da4f4b04 123 {
dudmuck 0:cb38da4f4b04 124 int i;
dudmuck 0:cb38da4f4b04 125 unsigned target = t.read_us() + TARGET_LATENCY;
dudmuck 0:cb38da4f4b04 126 printf("send_alarm() %u\n", target);
dudmuck 0:cb38da4f4b04 127
dudmuck 1:3199506bc2e5 128 for (i = 0; i < 5; i++) {
dudmuck 1:3199506bc2e5 129 transmit(target, cmd);
dudmuck 0:cb38da4f4b04 130 wait(0.1);
dudmuck 0:cb38da4f4b04 131 }
dudmuck 0:cb38da4f4b04 132 }
dudmuck 1:3199506bc2e5 133
dudmuck 1:3199506bc2e5 134 void debounce(DigitalIn* pin, uint8_t cmd)
dudmuck 1:3199506bc2e5 135 {
dudmuck 1:3199506bc2e5 136 if (!pin->read()) {
dudmuck 1:3199506bc2e5 137 int i;
dudmuck 1:3199506bc2e5 138 for (i = 0; i < 5; i++) {
dudmuck 1:3199506bc2e5 139 wait(0.01);
dudmuck 1:3199506bc2e5 140 if (pin->read()) {
dudmuck 1:3199506bc2e5 141 printf("trans\r\n");
dudmuck 1:3199506bc2e5 142 break;
dudmuck 1:3199506bc2e5 143 }
dudmuck 1:3199506bc2e5 144 }
dudmuck 1:3199506bc2e5 145 if (i == 5)
dudmuck 1:3199506bc2e5 146 send_alarm(cmd);
dudmuck 1:3199506bc2e5 147
dudmuck 1:3199506bc2e5 148 while (!pin->read())
dudmuck 1:3199506bc2e5 149 ;
dudmuck 1:3199506bc2e5 150 }
dudmuck 1:3199506bc2e5 151 }
dudmuck 2:0b7620bda2c9 152
dudmuck 4:19056d9707ef 153 void cmd_ocp(uint8_t ma)
dudmuck 4:19056d9707ef 154 {
dudmuck 4:19056d9707ef 155 if (ma < 130)
dudmuck 4:19056d9707ef 156 radio.RegOcp.bits.OcpTrim = (ma - 45) / 5;
dudmuck 4:19056d9707ef 157 else
dudmuck 4:19056d9707ef 158 radio.RegOcp.bits.OcpTrim = (ma + 30) / 10;
dudmuck 4:19056d9707ef 159 radio.write_reg(REG_OCP, radio.RegOcp.octet);
dudmuck 4:19056d9707ef 160
dudmuck 4:19056d9707ef 161 radio.RegOcp.octet = radio.read_reg(REG_OCP);
dudmuck 4:19056d9707ef 162 if (radio.RegOcp.bits.OcpTrim < 16)
dudmuck 4:19056d9707ef 163 ma = 45 + (5 * radio.RegOcp.bits.OcpTrim);
dudmuck 4:19056d9707ef 164 else if (radio.RegOcp.bits.OcpTrim < 28)
dudmuck 4:19056d9707ef 165 ma = (10 * radio.RegOcp.bits.OcpTrim) - 30;
dudmuck 4:19056d9707ef 166 else
dudmuck 4:19056d9707ef 167 ma = 240;
dudmuck 4:19056d9707ef 168 printf("Ocp: %dmA\r\n", ma);
dudmuck 4:19056d9707ef 169 }
dudmuck 4:19056d9707ef 170
dudmuck 2:0b7620bda2c9 171 void cmd_op(int dbm)
dudmuck 2:0b7620bda2c9 172 {
dudmuck 2:0b7620bda2c9 173 int i = dbm;
dudmuck 2:0b7620bda2c9 174 RegPdsTrim1_t pds_trim;
dudmuck 2:0b7620bda2c9 175 uint8_t adr;
dudmuck 2:0b7620bda2c9 176 if (radio.type == SX1276)
dudmuck 2:0b7620bda2c9 177 adr = REG_PDSTRIM1_SX1276;
dudmuck 2:0b7620bda2c9 178 else
dudmuck 2:0b7620bda2c9 179 adr = REG_PDSTRIM1_SX1272;
dudmuck 2:0b7620bda2c9 180
dudmuck 2:0b7620bda2c9 181 pds_trim.octet = radio.read_reg(adr);
dudmuck 2:0b7620bda2c9 182
dudmuck 2:0b7620bda2c9 183 if (radio.RegPaConfig.bits.PaSelect) {
dudmuck 2:0b7620bda2c9 184 /* PABOOST used: +2dbm to +17, or +20 */
dudmuck 2:0b7620bda2c9 185 if (i == 20) {
dudmuck 2:0b7620bda2c9 186 printf("+20dBm PADAC bias\r\n");
dudmuck 2:0b7620bda2c9 187 i -= 3;
dudmuck 2:0b7620bda2c9 188 pds_trim.bits.prog_txdac = 7;
dudmuck 2:0b7620bda2c9 189 radio.write_reg(adr, pds_trim.octet);
dudmuck 4:19056d9707ef 190 cmd_ocp(150);
dudmuck 2:0b7620bda2c9 191 }
dudmuck 2:0b7620bda2c9 192 if (i > 1)
dudmuck 2:0b7620bda2c9 193 radio.RegPaConfig.bits.OutputPower = i - 2;
dudmuck 2:0b7620bda2c9 194 } else {
dudmuck 2:0b7620bda2c9 195 /* RFO used: -1 to +14dbm */
dudmuck 2:0b7620bda2c9 196 if (i < 15)
dudmuck 2:0b7620bda2c9 197 radio.RegPaConfig.bits.OutputPower = i + 1;
dudmuck 2:0b7620bda2c9 198 }
dudmuck 2:0b7620bda2c9 199 radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
dudmuck 2:0b7620bda2c9 200
dudmuck 2:0b7620bda2c9 201 radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
dudmuck 2:0b7620bda2c9 202 if (radio.RegPaConfig.bits.PaSelect) {
dudmuck 2:0b7620bda2c9 203 printf("PA_BOOST ");
dudmuck 2:0b7620bda2c9 204 dbm = radio.RegPaConfig.bits.OutputPower + pds_trim.bits.prog_txdac - 2;
dudmuck 2:0b7620bda2c9 205 } else {
dudmuck 2:0b7620bda2c9 206 printf("RFO ");
dudmuck 2:0b7620bda2c9 207 dbm = radio.RegPaConfig.bits.OutputPower - 1;
dudmuck 2:0b7620bda2c9 208 }
dudmuck 2:0b7620bda2c9 209 printf("OutputPower:%ddBm\r\n", dbm);
dudmuck 2:0b7620bda2c9 210 }
dudmuck 2:0b7620bda2c9 211
dudmuck 0:cb38da4f4b04 212 int main()
dudmuck 0:cb38da4f4b04 213 {
dudmuck 0:cb38da4f4b04 214 printf("\r\nreset-tx\r\n");
dudmuck 0:cb38da4f4b04 215 t.start();
dudmuck 1:3199506bc2e5 216
dudmuck 3:d8b57eca8c45 217 pinA.mode(PullUp);
dudmuck 3:d8b57eca8c45 218 pinB.mode(PullUp);
dudmuck 3:d8b57eca8c45 219 pinC.mode(PullUp);
dudmuck 3:d8b57eca8c45 220 pinD.mode(PullUp);
dudmuck 1:3199506bc2e5 221
dudmuck 0:cb38da4f4b04 222 radio.rf_switch = rfsw_callback;
dudmuck 0:cb38da4f4b04 223
dudmuck 0:cb38da4f4b04 224 radio.set_frf_MHz(910.8);
dudmuck 0:cb38da4f4b04 225 lora.enable();
dudmuck 0:cb38da4f4b04 226 lora.setBw_KHz(500);
dudmuck 0:cb38da4f4b04 227 lora.setSf(11);
dudmuck 0:cb38da4f4b04 228
dudmuck 3:d8b57eca8c45 229 radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
dudmuck 3:d8b57eca8c45 230 #ifdef TARGET_DISCO_L072CZ_LRWAN1
dudmuck 3:d8b57eca8c45 231 radio.RegPaConfig.bits.PaSelect = 1;
dudmuck 4:19056d9707ef 232 cmd_op(20);
dudmuck 3:d8b57eca8c45 233 #else
dudmuck 0:cb38da4f4b04 234 /* RFO or PABOOST choice:
dudmuck 0:cb38da4f4b04 235 * SX1276 shield: RFO if using 900MHz, or PA_BOOST if using 433MHz
dudmuck 0:cb38da4f4b04 236 */
dudmuck 0:cb38da4f4b04 237 rfsw.input();
dudmuck 0:cb38da4f4b04 238 if (rfsw.read()) {
dudmuck 0:cb38da4f4b04 239 printf("LAS\r\n");
dudmuck 0:cb38da4f4b04 240 /* LAS HF=PA_BOOST LF=RFO */
dudmuck 0:cb38da4f4b04 241 if (radio.HF)
dudmuck 0:cb38da4f4b04 242 radio.RegPaConfig.bits.PaSelect = 1;
dudmuck 0:cb38da4f4b04 243 else
dudmuck 0:cb38da4f4b04 244 radio.RegPaConfig.bits.PaSelect = 0;
dudmuck 2:0b7620bda2c9 245 cmd_op(20);
dudmuck 0:cb38da4f4b04 246 } else {
dudmuck 0:cb38da4f4b04 247 /* MAS shield board, only RFO TX */
dudmuck 0:cb38da4f4b04 248 radio.RegPaConfig.bits.PaSelect = 0;
dudmuck 0:cb38da4f4b04 249 printf("MAS\r\n");
dudmuck 2:0b7620bda2c9 250 cmd_op(14);
dudmuck 0:cb38da4f4b04 251 }
dudmuck 0:cb38da4f4b04 252 rfsw.output();
dudmuck 3:d8b57eca8c45 253 #endif /* !TARGET_DISCO_L072CZ_LRWAN1 */
dudmuck 0:cb38da4f4b04 254 radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
dudmuck 0:cb38da4f4b04 255
dudmuck 0:cb38da4f4b04 256 /* constant payload length */
dudmuck 0:cb38da4f4b04 257 lora.RegPayloadLength = 7;
dudmuck 0:cb38da4f4b04 258 radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 4:19056d9707ef 259
dudmuck 4:19056d9707ef 260 /* lora.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);
dudmuck 4:19056d9707ef 261 lora.RegModemConfig2.sx1276bits.TxContinuousMode = 1;
dudmuck 4:19056d9707ef 262 radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet);
dudmuck 4:19056d9707ef 263 */
dudmuck 0:cb38da4f4b04 264 for (;;) {
dudmuck 3:d8b57eca8c45 265 debounce(&pinA, CMD_PINA);
dudmuck 3:d8b57eca8c45 266 debounce(&pinB, CMD_PINB);
dudmuck 3:d8b57eca8c45 267 debounce(&pinC, CMD_PINC);
dudmuck 3:d8b57eca8c45 268 debounce(&pinD, CMD_PIND);
dudmuck 0:cb38da4f4b04 269 } // ..for (;;)
dudmuck 0:cb38da4f4b04 270 }