Cleanup and reorganisation of state header file, new OpenRTX CPS data structure

pull/68/head
Silvano Seva 2022-03-26 16:42:02 +01:00
rodzic da22d6ff64
commit cbd3922325
20 zmienionych plików z 409 dodań i 259 usunięć

Wyświetl plik

@ -24,7 +24,7 @@ openrtx_src = ['openrtx/src/core/state.c',
'openrtx/src/core/battery.c',
'openrtx/src/core/graphics.cpp',
'openrtx/src/core/input.c',
'openrtx/src/core/calibUtils.c',
'openrtx/src/core/utils.c',
'openrtx/src/core/queue.c',
'openrtx/src/core/chan.c',
'openrtx/src/core/gps.c',

Wyświetl plik

@ -1,8 +1,8 @@
/***************************************************************************
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN, *
* Frederik Saraci IU2NRO, *
* Silvano Seva IU2KWO *
* Copyright (C) 2020 - 2022 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN, *
* Frederik Saraci IU2NRO, *
* Silvano Seva IU2KWO *
* *
* 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 *
@ -26,129 +26,262 @@
#include <datatypes.h>
#include <rtx.h>
/**
* \enum admit_t Enumeration type defining the admission criteria to a the
* channel.
*/
enum admit_t
{
ALWAYS = 0, /**< Always transmit when PTT is pressed */
FREE = 1, /**< Transmit only if channel si free */
TONE = 2, /**< Transmit on matching tone */
COLOR = 3 /**< Transmit only if color code is not used yet */
};
// Magic number to identify the binary file
#define CPS_MAGIC 0x52545843
// Codeplug version v0.1
#define CPS_VERSION_MAJOR 0
#define CPS_VERSION_MINOR 1
#define CPS_VERSION_NUMBER (CPS_VERSION_MAJOR << 8) | CPS_VERSION_MINOR
/******************************************************************************
* FM MODE *
******************************************************************************/
/**
* Data structure containing all and only the information for analog FM channels,
* like CTC/DCS tones.
* Data structure containing the tone information for analog FM channels.
* This is just a lookup table for the CTCSS frequencies and is not actually
* present in the codeplug binary data.
*/
#define MAX_TONE_INDEX 50
static const uint16_t ctcss_tone[MAX_TONE_INDEX] = {
static const uint16_t ctcss_tone[MAX_TONE_INDEX] =
{
670, 693, 719, 744, 770, 797, 825, 854, 885, 915, 948, 974, 1000, 1034,
1072, 1109, 1148, 1188, 1230, 1273, 1318, 1365, 1413, 1462, 1514, 1567,
1598, 1622, 1655, 1679, 1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928,
1966, 1995, 2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541
};
/**
* Data structure defining an analog-specific channel information such as tones.
*/
typedef struct
{
uint8_t rxToneEn : 1, /**< RX CTC/DCS tone enable */
rxTone : 7; /**< RX CTC/DCS tone index, squelch opens on match */
uint8_t txToneEn : 1, /**< TX CTC/DCS tone enable */
txTone : 7; /**< TX CTC/DCS tone index, sent alongside voice */
uint8_t rxToneEn : 1, //< RX CTC/DCS tone enable
rxTone : 7; //< RX CTC/DCS tone index
uint8_t txToneEn : 1, //< TX CTC/DCS tone enable
txTone : 7; //< TX CTC/DCS tone index
}
__attribute__((packed)) fmInfo_t;
__attribute__((packed)) fmInfo_t; // 2B
/******************************************************************************
* DMR MODE *
******************************************************************************/
/**
* Data structure containing all and only the information for DMR channels.
*/
typedef struct
{
uint8_t rxColorCode : 4, /**< Color code for RX squelch opening */
txColorCode : 4; /**< Color code sent during transmission */
uint8_t rxColorCode : 4, //< Color code for RX squelch opening
txColorCode : 4; //< Color code sent during transmission
uint8_t dmr_timeslot; /**< DMR timeslot, either 1 or 2 */
uint16_t contactName_index; /**< Index to retrieve data from contact list */
uint8_t dmr_timeslot; //< DMR timeslot, either 1 or 2
uint16_t contactName_index; //< Index to retrieve contact from list
}
__attribute__((packed)) dmrInfo_t;
__attribute__((packed)) dmrInfo_t; // 4B
/**
* Enumeration type defining the types of a DMR contact.
*/
enum dmrContactType_t
{
GROUP = 0, //< Group contact (Talkgroup)
PRIVATE = 1, //< Private contact
ALL = 2 //< Broadcast call
};
/**
* Data structure describing a DMR contact entry.
*/
typedef struct
{
uint32_t id; //< DMR id
uint8_t contactType : 2, //< Call type
rx_tone : 1, //< Call receive tone
_unused : 5; //< Padding
}
__attribute__((packed)) dmrContact_t; // 5B
/******************************************************************************
* M17 MODE *
******************************************************************************/
/**
* M17 channel modes.
*/
enum m17mode_t
{
DIGITAL_VOICE = 1, //< Digital Voice
DIGITAL_DATA = 2, //< Digital Data
DIGITAL_VOICE_DATA = 3 //< Digital Voice and Data
};
/**
* M17 channel encryption.
*/
enum m17crypto_t
{
PLAIN = 0, //< No encryption, plaintext data is sent
AES256 = 1, //< AES-256 Encryption
SCRAMBLER = 2 //< Scrambler
};
/**
* M17 gps operation.
*/
enum m17gps_t
{
NO_GPS = 0, //< No GPS information is sent
GPS_META = 1 //< GPS position is sent along with payload
};
/**
* Data structure containing all and only the information for M17 channels.
*/
typedef struct
{
uint8_t rxCan : 4, /**< Channel Access Number for RX squelch */
txCan : 4; /**< Channel Access Number for TX squelch */
uint16_t contactName_index; /**< Index to retrieve data from contact list */
uint8_t rxCan : 4, //< Channel Access Number for RX
txCan : 4; //< Channel Access Number for TX
uint8_t mode : 4, //< Channel operation mode
encr : 4; //< Encryption mode
uint8_t gps_mode; //< Channel GPS mode
uint16_t contactName_index; //< Index to retrieve data from contact list
}
__attribute__((packed)) m17Info_t;
__attribute__((packed)) m17Info_t; // 5B
/**
* Data structure containing all the information of a channel, either FM or DMR.
* Data structure describing M17-specific contact fields.
*/
typedef struct
{
uint8_t mode; /**< Operating mode */
uint8_t address[6]; //< M17 encoded address
}
__attribute__((packed)) m17Contact_t; // 6B
uint8_t bandwidth : 2, /**< Bandwidth */
admit_criteria : 2, /**< Admit criterion */
squelch : 1, /**< Squelch type: 0 = tight, 1 = normal */
rx_only : 1, /**< 1 means RX-only channel */
vox : 1, /**< VOX enable */
_padding : 1; /**< Padding to 8 bits */
float power; /**< Transmission power, in watt */
freq_t rx_frequency; /**< RX Frequency, in Hz */
freq_t tx_frequency; /**< TX Frequency, in Hz */
/******************************************************************************
* COMMON DATA STRUCTURES *
******************************************************************************/
uint8_t tot; /**< TOT x 15sec: 0-Infinite, 1=15s...33=495s */
uint8_t tot_rekey_delay; /**< TOT Rekey Delay: 0...255s */
/**
* Data structure for geolocation data
*/
typedef struct
{
int8_t ch_lat_int; //< Latitude integer part
uint16_t ch_lat_dec; //< Latitude decimal part
int16_t ch_lon_int; //< Longitude integer part
uint16_t ch_lon_dec; //< Longitude decimal part
uint16_t ch_altitude; //< Meters MSL. Stored +500
}
__attribute__((packed)) geo_t; // 9B
uint8_t emSys_index; /**< Emergency System: None, System1...32 */
uint8_t scanList_index; /**< Scan List: None, ScanList1...250 */
uint8_t groupList_index; /**< Group List: None, GroupList1...128 */
/**
* Data structure containing all the information of a channel.
*/
typedef struct
{
uint8_t mode; //< Operating mode
char name[16]; /**< Channel name */
uint8_t bandwidth : 2, //< Bandwidth
rx_only : 1, //< 1 means RX-only channel
_unused : 5; //< Padding to 8 bits
uint8_t power; //< P = 10dBm + n*0.2dBm, we store n
freq_t rx_frequency; //< RX Frequency, in Hz
freq_t tx_frequency; //< TX Frequency, in Hz
uint8_t scanList_index; //< Scan List: None, ScanList1...250
uint8_t groupList_index; //< Group List: None, GroupList1...128
char name[16]; //< Channel name
char descr[16]; //< Description of the channel
geo_t ch_location; //< Transmitter geolocation
union
{
fmInfo_t fm; /**< Information block for FM channels */
dmrInfo_t dmr; /**< Information block for DMR channels */
m17Info_t m17; /**< Information block for M17 channels */
fmInfo_t fm; //< Information block for FM channels
dmrInfo_t dmr; //< Information block for DMR channels
m17Info_t m17; //< Information block for M17 channels
};
}
__attribute__((packed)) channel_t;
__attribute__((packed)) channel_t; // 59B
/**
* Data structure containing all the information of a bank.
* Data structure describing a codeplug contact.
*/
typedef struct
{
char name[16]; /**< Bank name */
uint16_t member[64]; /**< Channel indexes */
char name[16]; //< Display name of the contact
uint8_t mode; //< Operating mode
union
{
dmrContact_t dmr; //< DMR specific contact info
m17Contact_t m17; //< M17 specific contact info
}
info; // 6B
}
__attribute__((packed)) contact_t; // 23B
/**
* Data structure containing all the information of a bank.
* Legacy data structure for brackwards compatibility.
*/
typedef struct
{
char name[16]; //< Bank name
uint16_t member[64]; //< Channel indexes
}
__attribute__((packed)) bank_t;
/**
* Data structure containing all the information of a contact.
* Data structure describing a bank header.
*/
typedef struct
{
char name[16]; /**< Contact name */
uint32_t id; /**< DMR ID: 24bit number, 1...16777215 */
uint8_t type; /**< Call Type: Group Call, Private Call or All Call */
bool receive_tone; /**< Call Receive Tone: No or yes */
char name[16];
uint16_t ch_count; //< Count of all the channels in this bank
}
__attribute__((packed)) contact_t;
__attribute__((packed)) bankHdr_t; // 18B + 2 * ch_count
/*
/**
* The codeplug binary structure is composed by:
* - A header struct
* - A variable length array of all the contacts
* - A variable length array of all the channels
* - A variable length array of the offsets to reach each bank
* - A binary dense structure of all the banks
*/
typedef struct
{
uint64_t magic; //< Magic number "RTXC"
uint16_t version_number; //< Version number for the cps structure
char author[16]; //< Author of the codeplug
char descr[16]; //< Description of the codeplug
uint64_t timestamp; //< unix timestamp of the codeplug
uint16_t ct_count; //< Number of stored contacts
uint16_t ch_count; //< Number of stored channels
uint16_t b_count; //< Number of stored banks
}
__attribute__((packed)) cps_header_t; // 52B
/**
* Create and return a viable channel for this radio.
* Suitable for default VFO settings or the creation of a new channel.
* Needs to be generated by a function frequency settings require details from the running hardware on limitations
* Needs to be generated by a function frequency settings require details from
* the running hardware on limitations.
*/
channel_t get_default_channel();
channel_t cps_getDefaultChannel();
#endif
#endif // CPS_H

Wyświetl plik

@ -20,13 +20,47 @@
#ifndef GPS_H
#define GPS_H
#include <state.h>
#include <interfaces/rtc.h>
#include <stdint.h>
/**
* Data structure representing a single satellite as part of a GPS fix.
*/
typedef struct
{
uint8_t id; // ID of the satellite
uint8_t elevation; // Elevation in degrees
uint16_t azimuth; // Azimuth in degrees
uint8_t snr; // Quality of the signal in range 0-99
}
sat_t;
/**
* Data structure representing the last state received from the GPS module.
*/
typedef struct
{
curTime_t timestamp; // Timestamp of the latest GPS update
uint8_t fix_quality; // 0: no fix, 1: GPS, 2: GPS SPS, 3: GPS PPS
uint8_t fix_type; // 0: no fix, 1: 2D, 2: 3D
uint8_t satellites_tracked; // Number of tracked satellites
uint8_t satellites_in_view; // Satellites in view
sat_t satellites[12]; // Details about satellites in view
uint32_t active_sats; // Bitmap representing which sats are part of the fix
float latitude; // Latitude coordinates
float longitude; // Longitude coordinates
float altitude; // Antenna altitude above mean sea level (geoid) in m
float speed; // Ground speed in km/h
float tmg_mag; // Course over ground, degrees, magnetic
float tmg_true; // Course over ground, degrees, true
}
gps_t;
/**
* This function perfoms the task of reading data from the GPS module,
* if available, enabled and ready, decode NMEA sentences and update
* the radio state with the retrieved data.
*/
void gps_taskFunc(char *line, int len, state_t *state);
void gps_taskFunc(char *line, int len);
#endif /* GPS_H */

Wyświetl plik

@ -26,50 +26,18 @@
#include <interfaces/rtc.h>
#include <cps.h>
#include <settings.h>
/**
* Data structure representing a single satellite as part of a GPS fix.
*/
typedef struct
{
uint8_t id; // ID of the satellite
uint8_t elevation; // Elevation in degrees
uint16_t azimuth; // Azimuth in degrees
uint8_t snr; // Quality of the signal in range 0-99
}
sat_t;
/**
* Data structure representing the last state received from the GPS module.
*/
typedef struct
{
curTime_t timestamp; // Timestamp of the latest GPS update
uint8_t fix_quality; // 0: no fix, 1: GPS, 2: GPS SPS, 3: GPS PPS
uint8_t fix_type; // 0: no fix, 1: 2D, 2: 3D
uint8_t satellites_tracked; // Number of tracked satellites
uint8_t satellites_in_view; // Satellites in view
sat_t satellites[12]; // Details about satellites in view
uint32_t active_sats; // Bitmap representing which sats are part of the fix
float latitude; // Latitude coordinates
float longitude; // Longitude coordinates
float altitude; // Antenna altitude above mean sea level (geoid) in m
float speed; // Ground speed in km/h
float tmg_mag; // Course over ground, degrees, magnetic
float tmg_true; // Course over ground, degrees, true
}
gps_t;
#include <gps.h>
/**
* Data structure representing the settings of the M17 mode.
*/
typedef struct
{
// char callsign[10];
char dst_addr[10];
}
m17_t;
/**
* Part of this structure has been commented because the corresponding
* functionality is not yet implemented.
@ -85,12 +53,6 @@ typedef struct
uint8_t ui_screen;
uint8_t tuner_mode;
//time_t rx_status_tv;
//bool rx_status;
//time_t tx_status_tv;
//bool tx_status;
uint16_t channel_index;
channel_t channel;
channel_t vfo_channel;
@ -130,12 +92,6 @@ extern state_t state;
*/
void state_init();
/**
* Write default values to OpenRTX settings and VFO Channel configuration.
* Writes out to flash and calls state_init again to reload it immediately.
*/
void defaultSettingsAndVfo();
/**
* This function terminates the radio state saving persistent settings to flash.
*/
@ -146,6 +102,11 @@ void state_terminate();
*/
void state_update();
/**
* Reset the fields of radio state containing user settings and VFO channel.
*/
void state_resetSettingsAndVfo();
/**
* The RTC and state.time are set to UTC time
* Use this function to get local time from UTC time based on timezone setting

Wyświetl plik

@ -1,7 +1,7 @@
/***************************************************************************
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN, *
* Silvano Seva IU2KWO *
* Copyright (C) 2020 - 2022 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN, *
* Silvano Seva IU2KWO *
* *
* 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 *
@ -32,6 +32,7 @@ extern "C" {
* frequencies outside the calibration points. It works by searching the two
* calibration points containing the target frequency and then by linearly
* interpolating the calibration parameter among these two points.
*
* @param freq: target frequency for which a calibration value has to be
* computed.
* @param calPoints: pointer to the vector containing the frequencies of the
@ -46,6 +47,15 @@ extern "C" {
uint8_t interpCalParameter(const freq_t freq, const freq_t *calPoints,
const uint8_t *param, const uint8_t elems);
/**
* Convert from "OpenRTX dBm" to watt.
* In OpenRTX cps power is stored as the coefficient n of the equation
* P(dBm) = 10 + 2*0.2.
*
* @param n: coefficient of the dBm equation.
* @return power in watt.
*/
float dBmToWatt(const uint8_t n);
#ifdef __cplusplus
}

Wyświetl plik

@ -1,8 +1,7 @@
#include <interfaces/platform.h>
#include <cps.h>
channel_t get_default_channel()
channel_t cps_getDefaultChannel()
{
channel_t channel;
channel.mode = OPMODE_FM;

Wyświetl plik

@ -30,13 +30,15 @@
/**
* This function parses a GPS NMEA sentence and updates radio state
*/
void gps_taskFunc(char *line, __attribute__((unused)) int len, state_t *state)
void gps_taskFunc(char *line, int len)
{
(void) len;
char nmea_id[3] = { 0 };
// Little mechanism to ensure that RTC is synced with GPS time only once.
static bool isRtcSyncronised = false;
if(!state->gps_set_time)
if(!state.gps_set_time)
{
isRtcSyncronised = false;
}
@ -55,27 +57,27 @@ void gps_taskFunc(char *line, __attribute__((unused)) int len, state_t *state)
struct minmea_sentence_rmc frame;
if (minmea_parse_rmc(&frame, line))
{
state->gps_data.latitude = minmea_tocoord(&frame.latitude);
state->gps_data.longitude = minmea_tocoord(&frame.longitude);
state->gps_data.timestamp.hour = frame.time.hours;
state->gps_data.timestamp.minute = frame.time.minutes;
state->gps_data.timestamp.second = frame.time.seconds;
state->gps_data.timestamp.day = 0;
state->gps_data.timestamp.date = frame.date.day;
state->gps_data.timestamp.month = frame.date.month;
state->gps_data.timestamp.year = frame.date.year;
state.gps_data.latitude = minmea_tocoord(&frame.latitude);
state.gps_data.longitude = minmea_tocoord(&frame.longitude);
state.gps_data.timestamp.hour = frame.time.hours;
state.gps_data.timestamp.minute = frame.time.minutes;
state.gps_data.timestamp.second = frame.time.seconds;
state.gps_data.timestamp.day = 0;
state.gps_data.timestamp.date = frame.date.day;
state.gps_data.timestamp.month = frame.date.month;
state.gps_data.timestamp.year = frame.date.year;
}
// Synchronize RTC with GPS UTC clock, only when fix is done
if((state->gps_set_time) &&
(state->gps_data.fix_quality > 0) && (!isRtcSyncronised))
if((state.gps_set_time) &&
(state.gps_data.fix_quality > 0) && (!isRtcSyncronised))
{
rtc_setTime(state->gps_data.timestamp);
rtc_setTime(state.gps_data.timestamp);
isRtcSyncronised = true;
}
state->gps_data.tmg_true = minmea_tofloat(&frame.course);
state->gps_data.speed = minmea_tofloat(&frame.speed) * KNOTS2KMH;
state.gps_data.tmg_true = minmea_tofloat(&frame.course);
state.gps_data.speed = minmea_tofloat(&frame.speed) * KNOTS2KMH;
} break;
case MINMEA_SENTENCE_GGA:
@ -83,24 +85,24 @@ void gps_taskFunc(char *line, __attribute__((unused)) int len, state_t *state)
struct minmea_sentence_gga frame;
if (minmea_parse_gga(&frame, line))
{
state->gps_data.fix_quality = frame.fix_quality;
state->gps_data.satellites_tracked = frame.satellites_tracked;
state->gps_data.altitude = minmea_tofloat(&frame.altitude);
state.gps_data.fix_quality = frame.fix_quality;
state.gps_data.satellites_tracked = frame.satellites_tracked;
state.gps_data.altitude = minmea_tofloat(&frame.altitude);
}
} break;
case MINMEA_SENTENCE_GSA:
{
state->gps_data.active_sats = 0;
state.gps_data.active_sats = 0;
struct minmea_sentence_gsa frame;
if (minmea_parse_gsa(&frame, line))
{
state->gps_data.fix_type = frame.fix_type;
state.gps_data.fix_type = frame.fix_type;
for (int i = 0; i < 12; i++)
{
if (frame.sats[i] != 0)
{
state->gps_data.active_sats |= 1 << (frame.sats[i] - 1);
state.gps_data.active_sats |= 1 << (frame.sats[i] - 1);
}
}
}
@ -115,17 +117,17 @@ void gps_taskFunc(char *line, __attribute__((unused)) int len, state_t *state)
// When the first sentence arrives, clear all the old data
if (frame.msg_nr == 1)
{
bzero(&state->gps_data.satellites[0], 12 * sizeof(sat_t));
bzero(&state.gps_data.satellites[0], 12 * sizeof(sat_t));
}
state->gps_data.satellites_in_view = frame.total_sats;
state.gps_data.satellites_in_view = frame.total_sats;
for (int i = 0; i < 4; i++)
{
int index = 4 * (frame.msg_nr - 1) + i;
state->gps_data.satellites[index].id = frame.sats[i].nr;
state->gps_data.satellites[index].elevation = frame.sats[i].elevation;
state->gps_data.satellites[index].azimuth = frame.sats[i].azimuth;
state->gps_data.satellites[index].snr = frame.sats[i].snr;
state.gps_data.satellites[index].id = frame.sats[i].nr;
state.gps_data.satellites[index].elevation = frame.sats[i].elevation;
state.gps_data.satellites[index].azimuth = frame.sats[i].azimuth;
state.gps_data.satellites[index].snr = frame.sats[i].snr;
}
}
} break;
@ -135,9 +137,9 @@ void gps_taskFunc(char *line, __attribute__((unused)) int len, state_t *state)
struct minmea_sentence_vtg frame;
if (minmea_parse_vtg(&frame, line))
{
state->gps_data.speed = minmea_tofloat(&frame.speed_kph);
state->gps_data.tmg_mag = minmea_tofloat(&frame.magnetic_track_degrees);
state->gps_data.tmg_true = minmea_tofloat(&frame.true_track_degrees);
state.gps_data.speed = minmea_tofloat(&frame.speed_kph);
state.gps_data.tmg_mag = minmea_tofloat(&frame.magnetic_track_degrees);
state.gps_data.tmg_true = minmea_tofloat(&frame.true_track_degrees);
}
} break;

Wyświetl plik

@ -25,22 +25,10 @@
#include <hwconfig.h>
#include <interfaces/platform.h>
#include <interfaces/nvmem.h>
#include <cps.h>
state_t state;
void defaultSettingsAndVfo()
{
//don't need to lock state mutex because this is called from a section
//that already does that - ui_updatefsm runs in a critical section in
//the ui thread
channel_t default_vfo = get_default_channel();
nvm_writeSettingsAndVfo( &default_settings, &default_vfo );
state_init();
}
void state_init()
{
/*
@ -59,7 +47,7 @@ void state_init()
*/
if(nvm_readVFOChannelData(&state.channel) < 0)
{
state.channel = get_default_channel();
state.channel = cps_getDefaultChannel();
}
/*
@ -114,6 +102,12 @@ void state_update()
#endif
}
void state_resetSettingsAndVfo()
{
state.settings = default_settings;
state.channel = cps_getDefaultChannel();
}
curTime_t state_getLocalTime(curTime_t utc_time)
{
curTime_t local_time = utc_time;

Wyświetl plik

@ -35,6 +35,7 @@
#include <queue.h>
#include <minmea.h>
#include <string.h>
#include <utils.h>
#ifdef HAS_GPS
#include <interfaces/gps.h>
#include <gps.h>
@ -92,20 +93,22 @@ void *ui_task(void *arg)
// If synchronization needed take mutex and update RTX configuration
if(sync_rtx)
{
float power = dBmToWatt(state.channel.power);
pthread_mutex_lock(&rtx_mutex);
rtx_cfg.opMode = state.channel.mode;
rtx_cfg.bandwidth = state.channel.bandwidth;
rtx_cfg.opMode = state.channel.mode;
rtx_cfg.bandwidth = state.channel.bandwidth;
rtx_cfg.rxFrequency = state.channel.rx_frequency;
rtx_cfg.txFrequency = state.channel.tx_frequency;
rtx_cfg.txPower = state.channel.power;
rtx_cfg.sqlLevel = state.settings.sqlLevel;
rtx_cfg.rxToneEn = state.channel.fm.rxToneEn;
rtx_cfg.rxTone = ctcss_tone[state.channel.fm.rxTone];
rtx_cfg.txToneEn = state.channel.fm.txToneEn;
rtx_cfg.txTone = ctcss_tone[state.channel.fm.txTone];
rtx_cfg.txPower = power;
rtx_cfg.sqlLevel = state.settings.sqlLevel;
rtx_cfg.rxToneEn = state.channel.fm.rxToneEn;
rtx_cfg.rxTone = ctcss_tone[state.channel.fm.rxTone];
rtx_cfg.txToneEn = state.channel.fm.txToneEn;
rtx_cfg.txTone = ctcss_tone[state.channel.fm.txTone];
// Copy new M17 source and destination addresses
strncpy(rtx_cfg.source_address, state.settings.callsign, 10);
strncpy(rtx_cfg.source_address, state.settings.callsign, 10);
strncpy(rtx_cfg.destination_address, state.m17_data.dst_addr, 10);
pthread_mutex_unlock(&rtx_mutex);
@ -298,7 +301,7 @@ void *gps_task(void *arg)
pthread_mutex_lock(&state_mutex);
// GPS readout is blocking, no need to delay here
gps_taskFunc(line, len, &state);
gps_taskFunc(line, len);
// Unlock state mutex
pthread_mutex_unlock(&state_mutex);

Wyświetl plik

@ -1,7 +1,7 @@
/***************************************************************************
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN, *
* Silvano Seva IU2KWO *
* Copyright (C) 2020 - 2022 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN, *
* Silvano Seva IU2KWO *
* *
* 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 *
@ -17,7 +17,8 @@
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <calibUtils.h>
#include <utils.h>
#include <math.h>
uint8_t interpCalParameter(const freq_t freq, const freq_t *calPoints,
const uint8_t *param, const uint8_t elems)
@ -49,3 +50,11 @@ uint8_t interpCalParameter(const freq_t freq, const freq_t *calPoints,
return interpValue;
}
float dBmToWatt(const uint8_t n)
{
float dBm = 10.0f + ((float) n) * 0.2f;
float power = pow(10.0f, (dBm - 30.0f)/10.0f);
return power;
}

Wyświetl plik

@ -764,10 +764,10 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
}
break;
case 3:
if (state.channel.power == 1.0f)
state.channel.power = 5.0f;
if (state.channel.power == 100)
state.channel.power = 135;
else
state.channel.power = 1.0f;
state.channel.power = 100;
*sync_rtx = true;
break;
case 4:
@ -1644,7 +1644,7 @@ void ui_updateFSM(event_t event, bool *sync_rtx)
if(msg.keys & KEY_ENTER)
{
ui_state.edit_mode = false;
defaultSettingsAndVfo();
state_resetSettingsAndVfo();
_ui_menuBack(MENU_SETTINGS);
}
else if(msg.keys & KEY_ESC)

Wyświetl plik

@ -22,6 +22,7 @@
#include <stdint.h>
#include <string.h>
#include <backup.h>
#include <utils.h>
#include <ui.h>
#include <interfaces/nvmem.h>
#include <interfaces/cps_io.h>
@ -718,7 +719,7 @@ bool _ui_drawMacroMenu()
gfx_print(layout.line1_pos, layout.top_font, TEXT_ALIGN_RIGHT,
yellow_fab413, "3 ");
gfx_print(layout.line1_pos, layout.top_font, TEXT_ALIGN_RIGHT,
color_white, "%.1gW", last_state.channel.power);
color_white, "%.1gW", dBmToWatt(last_state.channel.power));
// Second row
// Calculate symmetric second row position, line2_pos is asymmetric like main screen
point_t pos_2 = {layout.line1_pos.x, layout.line1_pos.y +

Wyświetl plik

@ -183,6 +183,8 @@ void nvm_loadHwInfo(hwInfo_t *info)
int nvm_readVFOChannelData(channel_t *channel)
{
memset(channel, 0x00, sizeof(channel_t));
gdxChannel_t chData;
AT24Cx_readData(vfoChannelBaseAddr, ((uint8_t *) &chData), sizeof(gdxChannel_t));
@ -190,17 +192,10 @@ int nvm_readVFOChannelData(channel_t *channel)
// Copy data to OpenRTX channel_t
channel->mode = chData.channel_mode + 1;
channel->bandwidth = chData.bandwidth;
channel->admit_criteria = chData.admit_criteria;
channel->squelch = chData.squelch;
channel->rx_only = chData.rx_only;
channel->vox = chData.vox;
channel->power = ((chData.power == 1) ? 5.0f : 1.0f);
channel->power = ((chData.power == 1) ? 135 : 100);
channel->rx_frequency = _bcd2bin(chData.rx_frequency) * 10;
channel->tx_frequency = _bcd2bin(chData.tx_frequency) * 10;
channel->tot = chData.tot;
channel->tot_rekey_delay = chData.tot_rekey_delay;
channel->emSys_index = chData.emergency_system_index;
channel->scanList_index = chData.scan_list_index;
channel->groupList_index = chData.group_list_index;
memcpy(channel->name, chData.name, sizeof(chData.name));
// Terminate string with 0x00 instead of 0xFF
@ -258,6 +253,8 @@ int cps_readChannelData(channel_t *channel, uint16_t pos)
if((pos <= 0) || (pos > maxNumChannels))
return -1;
memset(channel, 0x00, sizeof(channel_t));
// Channels are organized in 128-channel banks
uint8_t bank_num = (pos - 1) / 128;
// Note: pos is 1-based because an empty slot in a bank contains index 0
@ -310,16 +307,10 @@ int cps_readChannelData(channel_t *channel, uint16_t pos)
// Copy data to OpenRTX channel_t
channel->mode = chData.channel_mode + 1;
channel->bandwidth = chData.bandwidth;
channel->admit_criteria = chData.admit_criteria;
channel->squelch = chData.squelch;
channel->rx_only = chData.rx_only;
channel->vox = chData.vox;
channel->power = ((chData.power == 1) ? 5.0f : 1.0f);
channel->power = ((chData.power == 1) ? 135 : 100);
channel->rx_frequency = _bcd2bin(chData.rx_frequency) * 10;
channel->tx_frequency = _bcd2bin(chData.tx_frequency) * 10;
channel->tot = chData.tot;
channel->tot_rekey_delay = chData.tot_rekey_delay;
channel->emSys_index = chData.emergency_system_index;
channel->scanList_index = chData.scan_list_index;
channel->groupList_index = chData.group_list_index;
memcpy(channel->name, chData.name, sizeof(chData.name));
@ -427,11 +418,17 @@ int cps_readContactData(contact_t *contact, uint16_t pos)
memcpy(contact->name, contactData.name, sizeof(contactData.name));
// Terminate string with 0x00 instead of 0xFF
_addStringTerminator(contact->name, sizeof(contactData.name));
contact->mode = DMR;
// Copy contact DMR ID
contact->id = (contactData.id[0] | contactData.id[1] << 8 | contactData.id[2] << 16);
contact->info.dmr.id = contactData.id[0]
| (contactData.id[1] << 8)
| (contactData.id[2] << 16);
// Copy contact details
contact->type = contactData.type;
contact->receive_tone = contactData.receive_tone ? true : false;
contact->info.dmr.contactType = contactData.type;
contact->info.dmr.rx_tone = contactData.receive_tone ? true : false;
return 0;
}

Wyświetl plik

@ -21,6 +21,7 @@
#include <interfaces/nvmem.h>
#include <interfaces/delays.h>
#include <calibInfo_MDx.h>
#include <string.h>
#include <wchar.h>
#include "nvmData_MD3x0.h"
#include "W25Qx.h"
@ -171,6 +172,8 @@ int cps_readChannelData(channel_t *channel, uint16_t pos)
{
if((pos <= 0) || (pos > maxNumChannels)) return -1;
memset(channel, 0x00, sizeof(channel_t));
W25Qx_wakeup();
delayUs(5);
@ -182,16 +185,10 @@ int cps_readChannelData(channel_t *channel, uint16_t pos)
channel->mode = chData.channel_mode;
channel->bandwidth = chData.bandwidth;
channel->admit_criteria = chData.admit_criteria;
channel->squelch = chData.squelch;
channel->rx_only = chData.rx_only;
channel->vox = chData.vox;
channel->power = ((chData.power == 1) ? 5.0f : 1.0f);
channel->power = ((chData.power == 1) ? 135 : 100);
channel->rx_frequency = _bcd2bin(chData.rx_frequency) * 10;
channel->tx_frequency = _bcd2bin(chData.tx_frequency) * 10;
channel->tot = chData.tot;
channel->tot_rekey_delay = chData.tot_rekey_delay;
channel->emSys_index = chData.emergency_system_index;
channel->scanList_index = chData.scan_list_index;
channel->groupList_index = chData.group_list_index;
@ -309,11 +306,17 @@ int cps_readContactData(contact_t *contact, uint16_t pos)
{
contact->name[i] = ((char) (contactData.name[i] & 0x00FF));
}
contact->mode = DMR;
// Copy contact DMR ID
contact->id = (contactData.id[0] | contactData.id[1] << 8 | contactData.id[2] << 16);
contact->info.dmr.id = contactData.id[0]
| (contactData.id[1] << 8)
| (contactData.id[2] << 16);
// Copy contact details
contact->type = contactData.type;
contact->receive_tone = contactData.receive_tone ? true : false;
contact->info.dmr.contactType = contactData.type;
contact->info.dmr.rx_tone = contactData.receive_tone ? true : false;
return 0;
}

Wyświetl plik

@ -26,14 +26,14 @@
#include "nvmData_MDUV3x0.h"
#include "W25Qx.h"
const uint32_t zoneBaseAddr = 0x149E0; /**< Base address of zones */
const uint32_t zoneExtBaseAddr = 0x31000; /**< Base address of zone extensions */
const uint32_t vfoChannelBaseAddr = 0x2EF00; /**< Base address of VFO channel */
const uint32_t chDataBaseAddr = 0x110000; /**< Base address of channel data */
const uint32_t contactBaseAddr = 0x140000; /**< Base address of contacts */
const uint32_t maxNumChannels = 3000; /**< Maximum number of channels in memory */
const uint32_t maxNumZones = 250; /**< Maximum number of zones and zone extensions in memory */
const uint32_t maxNumContacts = 10000; /**< Maximum number of contacts in memory */
const uint32_t zoneBaseAddr = 0x149E0; /**< Base address of zones */
const uint32_t zoneExtBaseAddr = 0x31000; /**< Base address of zone extensions */
const uint32_t vfoChannelBaseAddr = 0x2EF00; /**< Base address of VFO channel */
const uint32_t chDataBaseAddr = 0x110000; /**< Base address of channel data */
const uint32_t contactBaseAddr = 0x140000; /**< Base address of contacts */
const uint32_t maxNumChannels = 3000; /**< Maximum number of channels in memory */
const uint32_t maxNumZones = 250; /**< Maximum number of zones and zone extensions in memory */
const uint32_t maxNumContacts = 10000; /**< Maximum number of contacts in memory */
/* This address has been chosen by OpenRTX to store the settings
* because it is empty (0xFF) and has enough free space */
const uint32_t settingsAddr = 0x6000;
@ -71,29 +71,23 @@ int _cps_readChannelAtAddress(channel_t *channel, uint32_t addr)
channel->mode = chData.channel_mode;
channel->bandwidth = chData.bandwidth;
channel->admit_criteria = chData.admit_criteria;
channel->squelch = chData.squelch;
channel->rx_only = chData.rx_only;
channel->vox = chData.vox;
channel->rx_frequency = _bcd2bin(chData.rx_frequency) * 10;
channel->tx_frequency = _bcd2bin(chData.tx_frequency) * 10;
channel->tot = chData.tot;
channel->tot_rekey_delay = chData.tot_rekey_delay;
channel->emSys_index = chData.emergency_system_index;
channel->scanList_index = chData.scan_list_index;
channel->groupList_index = chData.group_list_index;
if(chData.power == 3)
{
channel->power = 5.0f; /* High power -> 5W */
channel->power = 135; /* High power -> 5W = 37dBm */
}
else if(chData.power == 2)
{
channel->power = 2.5f; /* Mid power -> 2.5W */
channel->power = 120; /* Mid power -> 2.5W = 34dBm */
}
else
{
channel->power = 1.0f; /* Low power -> 1W */
channel->power = 100; /* Low power -> 1W = 30dBm */
}
/*
@ -181,6 +175,8 @@ int cps_readChannelData(channel_t *channel, uint16_t pos)
{
if((pos <= 0) || (pos > maxNumChannels)) return -1;
memset(channel, 0x00, sizeof(channel_t));
// Note: pos is 1-based because an empty slot in a zone contains index 0
uint32_t readAddr = chDataBaseAddr + (pos - 1) * sizeof(mduv3x0Channel_t);
return _cps_readChannelAtAddress(channel, readAddr);
@ -250,11 +246,17 @@ int cps_readContactData(contact_t *contact, uint16_t pos)
{
contact->name[i] = ((char) (contactData.name[i] & 0x00FF));
}
contact->mode = DMR;
// Copy contact DMR ID
contact->id = (contactData.id[0] | contactData.id[1] << 8 | contactData.id[2] << 16);
contact->info.dmr.id = contactData.id[0]
| (contactData.id[1] << 8)
| (contactData.id[2] << 16);
// Copy contact details
contact->type = contactData.type;
contact->receive_tone = contactData.receive_tone ? true : false;
contact->info.dmr.contactType = contactData.type;
contact->info.dmr.rx_tone = contactData.receive_tone ? true : false;
return 0;
}

Wyświetl plik

@ -26,14 +26,14 @@
#include "nvmData_MDUV3x0.h"
#include "W25Qx.h"
const uint32_t zoneBaseAddr = 0x149E0; /**< Base address of zones */
const uint32_t zoneExtBaseAddr = 0x31000; /**< Base address of zone extensions */
const uint32_t vfoChannelBaseAddr = 0x2EF00; /**< Base address of VFO channel */
const uint32_t chDataBaseAddr = 0x110000; /**< Base address of channel data */
const uint32_t contactBaseAddr = 0x140000; /**< Base address of contacts */
const uint32_t maxNumChannels = 3000; /**< Maximum number of channels in memory */
const uint32_t maxNumZones = 250; /**< Maximum number of zones and zone extensions in memory */
const uint32_t maxNumContacts = 10000; /**< Maximum number of contacts in memory */
const uint32_t zoneBaseAddr = 0x149E0; /**< Base address of zones */
const uint32_t zoneExtBaseAddr = 0x31000; /**< Base address of zone extensions */
const uint32_t vfoChannelBaseAddr = 0x2EF00; /**< Base address of VFO channel */
const uint32_t chDataBaseAddr = 0x110000; /**< Base address of channel data */
const uint32_t contactBaseAddr = 0x140000; /**< Base address of contacts */
const uint32_t maxNumChannels = 3000; /**< Maximum number of channels in memory */
const uint32_t maxNumZones = 250; /**< Maximum number of zones and zone extensions in memory */
const uint32_t maxNumContacts = 10000; /**< Maximum number of contacts in memory */
/* This address has been chosen by OpenRTX to store the settings
* because it is empty (0xFF) and has enough free space */
const uint32_t settingsAddr = 0x6000;
@ -42,7 +42,7 @@ const uint32_t settingsAddr = 0x6000;
* \internal Utility function to convert 4 byte BCD values into a 32-bit
* unsigned integer ones.
*/
uint32_t _bcd2bin(uint32_t bcd)
static uint32_t _bcd2bin(uint32_t bcd)
{
return ((bcd >> 28) & 0x0F) * 10000000 +
((bcd >> 24) & 0x0F) * 1000000 +
@ -57,7 +57,7 @@ uint32_t _bcd2bin(uint32_t bcd)
/**
* Used to read channel data from SPI flash into a channel_t struct
*/
int _cps_readChannelAtAddress(channel_t *channel, uint32_t addr)
static int _cps_readChannelAtAddress(channel_t *channel, uint32_t addr)
{
W25Qx_wakeup();
delayUs(5);
@ -71,29 +71,23 @@ int _cps_readChannelAtAddress(channel_t *channel, uint32_t addr)
channel->mode = chData.channel_mode;
channel->bandwidth = chData.bandwidth;
channel->admit_criteria = chData.admit_criteria;
channel->squelch = chData.squelch;
channel->rx_only = chData.rx_only;
channel->vox = chData.vox;
channel->rx_frequency = _bcd2bin(chData.rx_frequency) * 10;
channel->tx_frequency = _bcd2bin(chData.tx_frequency) * 10;
channel->tot = chData.tot;
channel->tot_rekey_delay = chData.tot_rekey_delay;
channel->emSys_index = chData.emergency_system_index;
channel->scanList_index = chData.scan_list_index;
channel->groupList_index = chData.group_list_index;
if(chData.power == 3)
{
channel->power = 5.0f; /* High power -> 5W */
channel->power = 135; /* High power -> 5W = 37dBm */
}
else if(chData.power == 2)
{
channel->power = 2.5f; /* Mid power -> 2.5W */
channel->power = 120; /* Mid power -> 2.5W = 34dBm */
}
else
{
channel->power = 1.0f; /* Low power -> 1W */
channel->power = 100; /* Low power -> 1W = 30dBm */
}
/*
@ -281,6 +275,8 @@ int cps_readChannelData(channel_t *channel, uint16_t pos)
{
if((pos <= 0) || (pos > maxNumChannels)) return -1;
memset(channel, 0x00, sizeof(channel_t));
// Note: pos is 1-based because an empty slot in a zone contains index 0
uint32_t readAddr = chDataBaseAddr + (pos - 1) * sizeof(mduv3x0Channel_t);
return _cps_readChannelAtAddress(channel, readAddr);
@ -350,11 +346,17 @@ int cps_readContactData(contact_t *contact, uint16_t pos)
{
contact->name[i] = ((char) (contactData.name[i] & 0x00FF));
}
contact->mode = DMR;
// Copy contact DMR ID
contact->id = (contactData.id[0] | contactData.id[1] << 8 | contactData.id[2] << 16);
contact->info.dmr.id = contactData.id[0]
| (contactData.id[1] << 8)
| (contactData.id[2] << 16);
// Copy contact details
contact->type = contactData.type;
contact->receive_tone = contactData.receive_tone ? true : false;
contact->info.dmr.contactType = contactData.type;
contact->info.dmr.rx_tone = contactData.receive_tone ? true : false;
return 0;
}

Wyświetl plik

@ -40,7 +40,7 @@ typedef struct
}
__attribute__((packed)) memory_t;
static const uint32_t validMagic = 0x5854504F; // "OPTX"
static const uint32_t validMagic = 0x584E504F; // "OPNX"
static const uint32_t baseAddress = 0x080E0000;
memory_t *memory = ((memory_t *) baseAddress);

Wyświetl plik

@ -22,9 +22,9 @@
#include <interfaces/radio.h>
#include <interfaces/gpio.h>
#include <calibInfo_GDx.h>
#include <calibUtils.h>
#include <hwconfig.h>
#include <algorithm>
#include <utils.h>
#include "radioUtils.h"
#include "HR_C6000.h"
#include "AT1846S.h"

Wyświetl plik

@ -23,10 +23,10 @@
#include <interfaces/radio.h>
#include <interfaces/gpio.h>
#include <calibInfo_MDx.h>
#include <calibUtils.h>
#include <hwconfig.h>
#include <ADC1_MDx.h>
#include <algorithm>
#include <utils.h>
#include "HR_C5000.h"
#include "SKY72310.h"

Wyświetl plik

@ -22,9 +22,9 @@
#include <interfaces/radio.h>
#include <interfaces/gpio.h>
#include <calibInfo_MDx.h>
#include <calibUtils.h>
#include <hwconfig.h>
#include <algorithm>
#include <utils.h>
#include "radioUtils.h"
#include "HR_C6000.h"
#include "AT1846S.h"