Browse Source

start implementing the core part of the irrigation controller...

This gets basic comms working and setunset working as well...  It
makes the LED blink!
irr_shared
John-Mark Gurney 3 years ago
parent
commit
62ddf5d243
2 changed files with 339 additions and 2 deletions
  1. +4
    -2
      Makefile
  2. +335
    -0
      irr_main.c

+ 4
- 2
Makefile View File

@@ -45,10 +45,12 @@ PROGS = lora.gw lora.irr
SRCS.lora.gw = main.c

SRCS.lora.irr = irr_main.c
SRCS.lora.irr+= comms.c
SRCS.lora.irr+= strobe_rng_init.c
SRCS.lora.irr+= $(STROBE_SRCS)

SRCS+= board.c
SRCS+= misc.c
SRCS+= strobe_rng_init.c
.if 0
SRCS+= rng_save.c
.endif
@@ -60,7 +62,7 @@ CFLAGS+= -g
# Strobe
.PATH: $(.CURDIR)/strobe
CFLAGS+= -I$(.CURDIR)/strobe
SRCS+= strobe.c \
STROBE_SRCS+= strobe.c \
x25519.c

# LoRamac (SX1276) radio code


+ 335
- 0
irr_main.c View File

@@ -1,4 +1,339 @@
/*-
* Copyright 2021 John-Mark Gurney.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/

#include "stm32l1xx.h"
#include "stm32l1xx_hal.h"

/* LoRaMac headers */
#include <board.h>
#include <adc.h>
#include <radio.h>
#include <delay.h>

/* lora-irr headers */
#include <misc.h>
#include <strobe_rng_init.h>
#include <comms.h>

enum {
CMD_TERMINATE = 1,
CMD_WAITFOR = 2,
CMD_RUNFOR = 3,
CMD_PING = 4,
CMD_SETUNSET = 5,
};

/*
* rxpktavail is initialized to true meaning that the data in rxpkt
* can be over written. When a packet is received, the data is copied
* to rxpkt, and then rxpktavail is set to false. Once the packet has
* been processed, it is set back to true.
*/
static uint8_t rxpkt[128];
static struct pktbuf rxpktbuf;
static volatile bool rxpktavail;

static uint8_t shared_key[] = "foobar";
static struct pktbuf shared_key_buf = (struct pktbuf){
.pkt = shared_key,
.pktlen = sizeof shared_key - 1,
};

static struct comms_state cs;

void
txdone(void)
{

/* restart Rx when Tx done */
Radio.Rx(0);
}

void
txtimeout(void)
{

/* restart Rx when Tx done */
Radio.Rx(0);
}

void
rxdone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{

if (rxpktavail) {
memcpy(rxpkt, payload, MIN(sizeof rxpkt, size));
rxpktbuf = (struct pktbuf){
.pkt = rxpkt,
.pktlen = size,
};
rxpktavail = false;
}
}

void
rxtimeout(void)
{

}

void
rxerr(void)
{
}

RadioEvents_t revents = {
.TxDone = txdone,
.TxTimeout = txtimeout,
.RxDone = rxdone,
.RxTimeout = rxtimeout,
.RxError = rxerr,
};

/*
* Seed the randomness from the radio. This is not a great
* seed, and is hard to gauge how much randomness is really
* there. Assuming about 1 bit per 8 bits looks pretty safe,
* so add 256 * 8 / 32 words.
*/
static void
radio_seed_rng(void)
{
#if 0
uint32_t v;
int i;

for (i = 0; i < 256 * 8 / 32; i++) {
v = Radio.Random();
strobe_seed_prng((uint8_t *)&v, sizeof v);
}
#endif
}

static void
analog_seed_rng(void)
{
#if 1
uint16_t v;
int i;

for (i = 0; i < 256 / 2; i++) {
/*
* Capture some ADC data. If pin is floating, 0xfff
* happens frequently, if pin is grounded, 0 happens
* frequently, filter these values out.
*/
do {
v = AdcReadChannel(&Adc, ADC_CHANNEL_21);
} while (v == 0 || v == 0xfff);
strobe_seed_prng((uint8_t *)&v, sizeof v);
}
#endif
}

static inline uint32_t
letoh_32(uint8_t *v)
{
return v[0] | (v[1] << 8) | (v[2] << 16) | (v[3] << 24);
}

struct chaninfo {
GPIO_TypeDef *bank;
uint16_t pinnum;
bool init;
} chans[] = {
[0] = { .bank = GPIOB, .pinnum = GPIO_PIN_5, .init = true, },
[1] = { .bank = GPIOB, .pinnum = GPIO_PIN_6, .init = true, },
[2] = { .bank = GPIOB, .pinnum = GPIO_PIN_7, .init = true, },
[3] = { .bank = GPIOB, .pinnum = GPIO_PIN_9, .init = true, },
[4] = { .bank = GPIOB, .pinnum = GPIO_PIN_8, .init = true, },
};
#define nitems(x) (sizeof(x) / sizeof *(x))

static void
set_chan(uint32_t chan, bool val)
{
struct chaninfo ci;

if (chan < nitems(chans)) {
ci = chans[chan];
HAL_GPIO_WritePin(ci.bank, ci.pinnum, val ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
}

static void
setup_gpio()
{
GPIO_InitTypeDef GPIO_InitStruct;
int i;

for (i = 0; i < nitems(chans); i++) {
GPIO_InitStruct = (GPIO_InitTypeDef){
.Pin = chans[i].pinnum,
.Mode = GPIO_MODE_OUTPUT_PP,
.Pull = GPIO_NOPULL,
.Speed = GPIO_SPEED_FREQ_LOW,
};
HAL_GPIO_Init(chans[i].bank, &GPIO_InitStruct);
set_chan(i, chans[i].init);
}
}

void
procmsg(struct pktbuf inbuf, struct pktbuf *outbuf)
{
uint32_t args[5];
int i, apos;

i = 1;
apos = 0;
while (i < inbuf.pktlen) {
if (i + 4 <= inbuf.pktlen) {
args[apos++] = letoh_32(&inbuf.pkt[i]);
i += 4;
}
}

outbuf->pkt[0] = inbuf.pkt[0];

switch (inbuf.pkt[0]) {
case CMD_SETUNSET:
if (apos == 2)
set_chan(args[0], args[1]);
break;

default:
outbuf->pkt[0] = 0;
break;
}

outbuf->pktlen = 1;
}

int
main()
{

strobe_rng_init();

BoardInitMcu();

Radio.Init(&revents);

analog_seed_rng();

radio_seed_rng();

strobe_rng_save();

setup_gpio();

/* turn on LED */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);

Radio.SetModem(MODEM_LORA);
Radio.SetChannel(914350 * 1000);

/* RX/TX parameters */
const uint8_t modem = MODEM_LORA;
const uint8_t bandwidth = 0 /* 128 kHz */;
const uint8_t datarate = 7 /* 128 chips */;
const uint8_t coderate = 1 /* 4/5 */;
const uint8_t preambleLen = 4 /* symbols */;
const uint8_t fixLen = 0 /* variable */;
const uint8_t crcOn = 1 /* on */;
const uint8_t freqHopOn = 0 /* off */;
const bool iqInverted = false /* not inverted */;

Radio.SetRxConfig(modem, bandwidth, datarate, coderate, 0/*afc*/,
preambleLen, 5/*symTimeout*/, fixLen, 0/*payloadlen*/, crcOn,
freqHopOn, 0/*hopPeriod*/, iqInverted, true/*rxcont*/);
Radio.SetTxConfig(modem, 11/*power*/, 0/*fdev*/, bandwidth, datarate,
coderate, preambleLen, fixLen, crcOn, freqHopOn, 0/*hopPeriod*/,
iqInverted, 1000/*timeout*/);

/* blink led */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
DelayMs(300);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);

Radio.Rx(0);

comms_init(&cs, procmsg, &shared_key_buf);

uint8_t txbuf[128] = "i'mhere";
struct pktbuf txpktbuf;

txpktbuf = (struct pktbuf){
.pkt = txbuf,
.pktlen = 8,
};
Radio.Send(txpktbuf.pkt, txpktbuf.pktlen);

rxpktavail = true;

//Radio.Rx(0);

loop:
BoardLowPowerHandler();
if (Radio.IrqProcess != NULL)
Radio.IrqProcess();

if (!rxpktavail) {
txpktbuf = (struct pktbuf){
.pkt = txbuf,
.pktlen = sizeof txbuf,
};
/* process available packet */
comms_process(&cs, rxpktbuf, &txpktbuf);

rxpktavail = true;

if (txpktbuf.pktlen) {
int i;
for (i = 0; i < 1; i++) {
DelayMs(20);
Radio.Send(txpktbuf.pkt, txpktbuf.pktlen);
}

#if 0
/* blink led */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
DelayMs(300);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
DelayMs(300);
#endif
}

#if 0
/* blink led */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
DelayMs(300);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
#endif
}
goto loop;
}

Loading…
Cancel
Save