Text menu driven ANSI/VT100 console test utility for LoRa transceivers

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 LR1110, then import LR1110 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.
If you're using Type1SJ select target DISCO_L072CZ_LRWAN1 and import sx126x driver into your program.

This is VT100 text-based menu driven test program for SX12xx transceiver devices.
Serial console is divided into horizontally into top half and bottom half.
The bottom half serves as scrolling area to log activity.
The top half serves as menu, to configure the radio.
For all devices, the serial console operates at 115200 8N1, and requires terminal with ANSI-VT100 capability, such as putty/teraterm/minicom etc.
Use program only with keyboard up/down/left/right keys. Enter to change an item, or number for value item. Some items are single bit, requiring only enter key to toggle. Others with fixed choices give a drop-down menu.

radio.h

Committer:
dudmuck
Date:
2021-09-16
Revision:
14:14b9e1c08bfc
Parent:
13:8ce61a1897ab

File content as of revision 14:14b9e1c08bfc:

#include "sx12xx.h"

#ifdef SX127x_H 
#include "sx127x_lora.h"
#include "sx127x_fsk.h"
#endif /* SX127x_H */

#define FIRST_CHIP_MENU_ROW        3
#define LAST_CHIP_MENU_ROW          (MAX_MENU_ROWS-5)

#if defined(SX128x_H)
    #define MAX_MENU_ROWS             16
    #define MAX_MENU_COLUMNS           6
#elif defined(SX127x_H)
    #define MAX_MENU_ROWS             16
    #define MAX_MENU_COLUMNS           6
#elif defined(SX126x_H)
    //#define MEMSCAN
    #define MAX_MENU_ROWS             17
    #define MAX_MENU_COLUMNS           6
#elif defined(SX1265_H)
    #define MAX_MENU_ROWS             23
    #define MAX_MENU_COLUMNS          14
#endif

#define PA_OFF_DBM      -127

typedef enum {
    _READ_,
    _WRITE_
} action_e;

typedef struct {
    uint8_t row;
    uint8_t col;
} pos_t;

#define _ITEM_VALUE      0xbb
#define _ITEM_DROPDOWN   0xaa
#define _ITEM_BUTTON     0xcc
#define _ITEM_TOGGLE     0xdd

typedef enum {
    MENUMODE_NONE = 0,
    MENUMODE_ENTRY,
    MENUMODE_DROPDOWN,
    MENUMODE_REDRAW,
    MENUMODE_REINIT_MENU,
} menuMode_e;

typedef struct {
    uint8_t itemType;

    const char* const * printed_strs;   // displayed values index from read callback return
    const char* const * selectable_strs;   // choices

    unsigned (*const read)(bool forWriting);
    menuMode_e (*const write)(unsigned);
} dropdown_item_t;

typedef struct {
    uint8_t itemType;

    unsigned width; // num columns printed

    void (*const print)(void);
    bool (*const write)(const char*); // NULL for read-only.  return true: redraw menu
} value_item_t;

typedef struct {
    uint8_t itemType;

    const char * const label;
    void (*const push)(void);
} button_item_t;

typedef struct {
    uint8_t itemType;

    const char * const label0;
    const char * const label1;
    bool (*const read)(void);
    bool (*const push)(void);
} toggle_item_t;

#define FLAG_MSGTYPE_ALL            0x07
#define FLAG_MSGTYPE_PKT            0x01
#define FLAG_MSGTYPE_PER            0x02
#define FLAG_MSGTYPE_PING           0x04

typedef struct {
    pos_t pos;  // on screen position, both row & col with 1 starting value
    const char* const label;

    const void* const itemPtr;

    uint8_t flags;

    const void* refreshReadItem;    /* other item to be read after activation */
} menu_t;


typedef struct {
    menuMode_e mode;
    uint8_t sel_idx;
    const menu_t* sm;
    uint8_t dropdown_col;
} menuState_t;

extern menuState_t menuState;
extern menu_t* menu[][MAX_MENU_COLUMNS];
extern int8_t StopMenuCols[];

extern uint8_t entry_buf_idx;
extern char entry_buf[];

void log_printf(const char* format, ...);

typedef struct {
    unsigned hz;
    uint8_t bwf;
} rxbw_t;

typedef struct
{
    void    (*const TxDone_botHalf)(void);    // read irqAt for timestamp of interrupt
    void    (*const RxDone)(uint8_t size, float rssi, float snr);    // read radio.rx_buf for payload, irqAt for timestamp of interrupt
} RadioEvents_t;

void printRxPkt(uint8_t size);

class Radio {
    public:
        static const char* const chipNum_str;

        static void boardInit(const RadioEvents_t* e);
        static void hw_reset(void);
        static void clearIrqFlags(void);
        static void readChip(void);
        static void tx_carrier(void);
        static void tx_preamble(void);
        static void txPkt(void);
        static void Rx(void);
        static void setFS(void);

        static const value_item_t tx_dbm_item;

        static const menu_t* get_modem_menu(void);
        static const menu_t* get_modem_sub_menu(void);

        static unsigned pktType_read(bool);
        static menuMode_e pktType_write(unsigned);
        static const char* const pktType_strs[];

        static void tx_dbm_print(void);
        static bool tx_dbm_write(const char*);

        static unsigned tx_ramp_read(bool);
        static menuMode_e tx_ramp_write(unsigned);
        static const char* tx_ramp_strs[];

        static const char* const opmode_status_strs[];
        static const char* const opmode_select_strs[];
        static unsigned opmode_read(bool);
        static menuMode_e opmode_write(unsigned);

        static uint8_t get_payload_length(void);
        static void set_payload_length(uint8_t);

        static void tx_payload_length_print(void);
        static bool tx_payload_length_write(const char*);
#ifdef SX127x_H 
        static SX127x radio;
        static SX127x_lora lora;
        static SX127x_fsk fsk;
        static void rfsw_callback(void);
        static void ocp(uint8_t ma);
        static InterruptIn dio0;
        static InterruptIn dio1;
#elif defined(SX126x_H)
        static SX126x radio;
        static ModulationParams_t mpFSK, mpLORA;
        static PacketParams_t ppFSK, ppLORA;
#elif defined(SX128x_H)
        static SX128x radio;
        static uint8_t tx_param_buf[];
        static ModulationParams_t mpFLRC, mpBLE_GFSK, mpLORA;
        static PacketParams_t ppGFSK, ppFLRC, ppLORA, ppBLE;
#elif defined(SX1265_H)
        static SX1265 radio;
        static uint8_t tx_param_buf[];
        static uint8_t pa_config_buf[];
        static irq_t memRegRead(uint32_t addr, uint16_t len_dwords, uint8_t *dest);
        static uint32_t from_big_endian32(const uint8_t *in);
        static void print_stat(stat_t stat);
        static uint8_t gfsk_pp_buf[];
        static uint8_t gfsk_mp_buf[];
        static uint8_t lora_pp_buf[];
        static uint8_t lora_mp_buf[];
#else
        #error import radio driver library
#endif
        static bool service(int8_t);
        static const menu_t common_menu[];

        static void test(void);

        static unsigned read_register(unsigned);
        static void write_register(unsigned, unsigned);

    private:
        static const RadioEvents_t* RadioEvents;

        static void txDoneBottom(void);
        static void cadDone(bool);

        static const menu_t lora_menu[];

        static LowPowerTimer lpt;
#if defined(SX128x_H)
        #include "radio_sx128x_private.h"
#elif defined(SX127x_H)
        #include "radio_sx127x_private.h"
#elif defined(SX126x_H)
        #include "radio_sx126x_private.h"
#elif defined(SX1265_H)
        #include "radio_lr1110_private.h"
#endif
};