From ec23dd8edfcce7c523a0c33b931253d9959dd93c Mon Sep 17 00:00:00 2001 From: Arjan Onwezen Date: Sun, 30 Jan 2022 05:12:46 -0500 Subject: [PATCH 01/15] some improvements to screen navigation --- firmware/common/ui_focus.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/firmware/common/ui_focus.cpp b/firmware/common/ui_focus.cpp index 61f37a0b..1b7e23dc 100644 --- a/firmware/common/ui_focus.cpp +++ b/firmware/common/ui_focus.cpp @@ -142,7 +142,23 @@ static int32_t rect_distances( return -1; } - return (std::abs(perpendicular_axis_end - perpendicular_axis_start) + 1) * (on_axis_distance + 1); + + switch(direction) { + case KeyEvent::Right: + case KeyEvent::Left: + return ((std::abs(perpendicular_axis_end - perpendicular_axis_start) + 1) ^ 3) * sqrt((on_axis_distance + 1)); + break; + + case KeyEvent::Up: + case KeyEvent::Down: + return (sqrt(std::abs(perpendicular_axis_end - perpendicular_axis_start) + 1)) * ((on_axis_distance + 1) ^ 3); + break; + + default: + return 0; + } + + } void FocusManager::update( From d5a1733c1c008d31e0ad97a3888f642d4e0b17b7 Mon Sep 17 00:00:00 2001 From: Brumi-2021 Date: Sat, 5 Mar 2022 21:39:53 +0100 Subject: [PATCH 02/15] Solving_mic_saturation_and_spectrum_armonics_Mic_App --- firmware/application/apps/ui_mictx.cpp | 57 +++- firmware/application/apps/ui_mictx.hpp | 57 +++- firmware/application/audio.cpp | 4 +- firmware/application/audio.hpp | 6 +- firmware/common/ak4951.cpp | 389 ++++++++++++++++++++----- firmware/common/ak4951.hpp | 63 ++-- firmware/common/wm8731.hpp | 5 +- hackrf | 2 +- 8 files changed, 465 insertions(+), 118 deletions(-) diff --git a/firmware/application/apps/ui_mictx.cpp b/firmware/application/apps/ui_mictx.cpp index 0e2c9c47..bda0f278 100644 --- a/firmware/application/apps/ui_mictx.cpp +++ b/firmware/application/apps/ui_mictx.cpp @@ -24,6 +24,10 @@ #include "baseband_api.hpp" #include "audio.hpp" + +#include "wm8731.hpp" +using wolfson::wm8731::WM8731; + #include "tonesets.hpp" #include "portapack_hal.hpp" #include "string_format.hpp" @@ -34,6 +38,10 @@ using namespace tonekey; using namespace portapack; + +WM8731 audio_codec_wm8731 { i2c0, 0x1a }; + + namespace ui { void MicTXView::focus() { @@ -178,7 +186,7 @@ void MicTXView::rxaudio(bool is_on) { baseband::run_image(portapack::spi_flash::image_tag_mic_tx); audio::output::stop(); - audio::input::start(); + audio::input::start(ak4951_alc_GUI_selected); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored) portapack::pin_i2s0_rx_sda.mode(3); configure_baseband(); } @@ -203,10 +211,12 @@ MicTXView::MicTXView( baseband::run_image(portapack::spi_flash::image_tag_mic_tx); - add_children({ - &labels, + + if ( audio_codec_wm8731.detected() ) { + add_children({ + &labels_WM8731, // we have audio codec WM8731, same MIC menu as original. &vumeter, - &options_gain, + &options_gain, // MIC GAIN float factor on the GUI. // &check_va, &field_va, &field_va_level, @@ -229,6 +239,37 @@ MicTXView::MicTXView( &field_rxamp, &tx_button }); + + } else { + add_children({ + &labels_AK4951, // we have audio codec AK4951, enable Automatic Level Control + &vumeter, + &options_gain, + &options_ak4951_alc_mode, +// &check_va, + &field_va, + &field_va_level, + &field_va_attack, + &field_va_decay, + &field_bw, + &field_rfgain, + &field_rfamp, + &options_mode, + &field_frequency, + &options_tone_key, + &check_rogerbeep, + &check_rxactive, + &field_volume, + &field_rxbw, + &field_squelch, + &field_rxfrequency, + &field_rxlna, + &field_rxvga, + &field_rxamp, + &tx_button + }); + + } tone_keys_populate(options_tone_key); options_tone_key.on_change = [this](size_t i, int32_t) { @@ -242,6 +283,12 @@ MicTXView::MicTXView( }; options_gain.set_selected_index(1); // x1.0 + options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) { + ak4951_alc_GUI_selected = v; + audio::input::start(ak4951_alc_GUI_selected); + }; + // options_ak4951_alc_mode.set_selected_index(0); + tx_frequency = transmitter_model.tuning_frequency(); field_frequency.set_value(transmitter_model.tuning_frequency()); field_frequency.set_step(receiver_model.frequency_step()); @@ -478,7 +525,7 @@ MicTXView::MicTXView( set_tx(false); audio::set_rate(audio::Rate::Hz_24000); - audio::input::start(); + audio::input::start(ak4951_alc_GUI_selected); // originally , audio::input::start(); (we added parameter) } MicTXView::~MicTXView() { diff --git a/firmware/application/apps/ui_mictx.hpp b/firmware/application/apps/ui_mictx.hpp index 9084047a..aaab059c 100644 --- a/firmware/application/apps/ui_mictx.hpp +++ b/firmware/application/apps/ui_mictx.hpp @@ -83,6 +83,7 @@ private: bool rx_enabled { false }; uint32_t tone_key_index { }; float mic_gain { 1.0 }; + uint8_t ak4951_alc_GUI_selected { 0 }; uint32_t audio_level { 0 }; uint32_t va_level { }; uint32_t attack_ms { }; @@ -106,8 +107,8 @@ private: bool enable_lsb { false }; - Labels labels { - { { 3 * 8, 1 * 8 }, "MIC. GAIN:", Color::light_grey() }, + Labels labels_WM8731 { + { { 3 * 8, 1 * 8 }, "MIC-GAIN:", Color::light_grey() }, { { 3 * 8, 3 * 8 }, "F:", Color::light_grey() }, { { 15 * 8, 3 * 8 }, "BW: FM kHz", Color::light_grey() }, { { 3 * 8, 5 * 8 }, "GAIN:", Color::light_grey() }, @@ -118,15 +119,36 @@ private: { {12 * 8, 10 * 8 }, "ATT:", Color::light_grey() }, { {20 * 8, 10 * 8 }, "DEC:", Color::light_grey() }, { { 4 * 8, ( 13 * 8 ) - 2 }, "TONE KEY:", Color::light_grey() }, - { { 9 * 8, 23 * 8 }, "VOL:", Color::light_grey() }, - { {17 * 8, 23 * 8 }, "FM RXBW:", Color::light_grey() }, + { { 7 * 8, 23 * 8 }, "VOL:", Color::light_grey() }, + { {15 * 8, 23 * 8 }, "FM RXBW:", Color::light_grey() }, { {17 * 8, 25 * 8 }, "SQ:", Color::light_grey() }, { { 5 * 8, 25 * 8 }, "F:", Color::light_grey() }, { { 5 * 8, 27 * 8 }, "LNA:", Color::light_grey()}, { {12 * 8, 27 * 8 }, "VGA:", Color::light_grey()}, { {19 * 8, 27 * 8 }, "AMP:", Color::light_grey()} }; - + Labels labels_AK4951 { + { { 3 * 8, 1 * 8 }, "MIC-GAIN:", Color::light_grey() }, + { { 17 * 8, 1 * 8 }, "ALC", Color::light_grey() }, + { { 3 * 8, 3 * 8 }, "F:", Color::light_grey() }, + { { 15 * 8, 3 * 8 }, "BW: FM kHz", Color::light_grey() }, + { { 3 * 8, 5 * 8 }, "GAIN:", Color::light_grey() }, + { {11 * 8, 5 * 8 }, "Amp:", Color::light_grey() }, + { { 18 * 8, (5 * 8) }, "Mode:", Color::light_grey() }, + { { 3 * 8, 8 * 8 }, "TX Activation:", Color::light_grey() }, + { { 4 * 8, 10 * 8 }, "LVL:", Color::light_grey() }, + { {12 * 8, 10 * 8 }, "ATT:", Color::light_grey() }, + { {20 * 8, 10 * 8 }, "DEC:", Color::light_grey() }, + { { 4 * 8, ( 13 * 8 ) - 2 }, "TONE KEY:", Color::light_grey() }, + { { 7 * 8, 23 * 8 }, "VOL:", Color::light_grey() }, + { {15 * 8, 23 * 8 }, "FM RXBW:", Color::light_grey() }, + { {17 * 8, 25 * 8 }, "SQ:", Color::light_grey() }, + { { 5 * 8, 25 * 8 }, "F:", Color::light_grey() }, + { { 5 * 8, 27 * 8 }, "LNA:", Color::light_grey()}, + { {12 * 8, 27 * 8 }, "VGA:", Color::light_grey()}, + { {19 * 8, 27 * 8 }, "AMP:", Color::light_grey()} + }; + VuMeter vumeter { { 0 * 8, 1 * 8, 2 * 8, 33 * 8 }, 12, @@ -135,7 +157,7 @@ private: OptionsField options_gain { - { 13 * 8, 1 * 8 }, + { 12 * 8, 1 * 8 }, 4, { { "x0.5", 5 }, @@ -145,6 +167,25 @@ private: } }; + OptionsField options_ak4951_alc_mode { + { 20 * 8, 1 * 8 }, // Coordinates are: int:x (px), int:y (px) + 11, + { + { " OFF-20kHz", 0 }, // Nothing changed from ORIGINAL,keeping ALL programm. AK4951 Dig. block->OFF) + { "+12dB-6kHz", 1 }, // ALC-> on, (+12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + { "+09dB-6kHz", 2 }, // ALC-> on, (+09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + { "+06dB-6kHz", 3 }, // ALC-> on, (+06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + { "+03dB-2kHz", 4 }, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 3,5k + Pre-amp Mic (+21dB=original)+ EQ boosting ~<2kHz (f0~1k1,fb:1,7K, k=1,8) + { "+03dB-4kHz", 5 }, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 4kHz + Pre-amp Mic (+21dB=original)+ EQ boosting ~<3kHz (f0~1k4,fb~2,4k, k=1,8) + { "+03dB-6kHz", 6 }, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + { "+00dB-6kHz", 7 }, // ALC-> on, (+00dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + { "-03dB-6kHz", 8 }, // ALC-> on, (-03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + { "-06dB-6kHz", 9 }, // ALC-> on, (-06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + { "-09dB-6kHz", 10 }, // ALC-> on, (-09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -3dB (18dB's) + { "-12dB-6kHz", 11 }, // ALC-> on, (-12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -6dB (15dB's) + } + }; + FrequencyField field_frequency { { 5 * 8, 3 * 8 }, }; @@ -244,7 +285,7 @@ private: }; NumberField field_volume { - { 13 * 8, 23 * 8 }, + { 11* 8, 23 * 8 }, 2, { 0, 99 }, 1, @@ -252,7 +293,7 @@ private: }; OptionsField field_rxbw { - { 25 * 8, 23 * 8}, + { 23* 8, 23 * 8}, 3, { {"8k5", 0}, diff --git a/firmware/application/audio.cpp b/firmware/application/audio.cpp index 4ba23acc..ce32076c 100644 --- a/firmware/application/audio.cpp +++ b/firmware/application/audio.cpp @@ -168,8 +168,8 @@ void speaker_mute() { namespace input { -void start() { - audio_codec->microphone_enable(); +void start(int8_t alc_mode) { + audio_codec->microphone_enable(alc_mode); // added user-GUI selection for AK4951, ALC mode parameter. i2s::i2s0::rx_start(); } diff --git a/firmware/application/audio.hpp b/firmware/application/audio.hpp index b02e42aa..56301ee8 100644 --- a/firmware/application/audio.hpp +++ b/firmware/application/audio.hpp @@ -49,7 +49,7 @@ public: virtual volume_range_t headphone_gain_range() const = 0; virtual void set_headphone_volume(const volume_t volume) = 0; - virtual void microphone_enable() = 0; + virtual void microphone_enable(int8_t alc_mode) = 0; // added user-GUI AK4951 ,selected ALC mode. virtual void microphone_disable() = 0; virtual size_t reg_count() const = 0; @@ -59,7 +59,7 @@ public: namespace output { -void start(); +void start(); // this other start(),no changed. ,in namespace output , used to config audio playback mode, void stop(); void mute(); @@ -72,7 +72,7 @@ void speaker_unmute(); namespace input { -void start(); +void start(int8_t alc_mode); // added parameter user-GUI select AK4951-ALC mode for config mic path,(recording mode in datasheet), void stop(); } /* namespace input */ diff --git a/firmware/common/ak4951.cpp b/firmware/common/ak4951.cpp index 3556e0a5..d94bbb0b 100644 --- a/firmware/common/ak4951.cpp +++ b/firmware/common/ak4951.cpp @@ -212,90 +212,347 @@ void AK4951::speaker_disable() { set_speaker_power(false); } -void AK4951::microphone_enable() { -// map.r.digital_mic.DMIC = 0; -// update(Register::DigitalMic); +void AK4951::microphone_enable(int8_t alc_mode) { +// alc_mode =0 = (OFF =same as original code = NOT using AK4951 Programmable digital filter block), +// alc_mode >1 (with DIGITAL FILTER BLOCK , example : 1:(+12dB) , 2:(+9dB)", 3:(+6dB), ...) + +// map.r.digital_mic.DMIC = 0; // originally commented code +// update(Register::DigitalMic); // originally commented code + +uint_fast8_t mgain =0b0111; // Pre-amp mic (Original code, =0b0111 (+21dB's=7x3dBs),(Max is NOT 0b1111!, it is 0b1010=+30dBs=10x3dBs) + +map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2 , our ext. MONO MIC is connected here LIN2 in Portapack. +map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2 , Not used ,not connected ,but no problem. +map.r.signal_select_2.MICL = 0; // MPWR = 2.4V (it has two possible settings , 2.4V or 2.0V) , (majority smarthphones around 2V , range 1V-5V) +update(Register::SignalSelect2); + +// ------Common code part, = original setting conditions, it is fine for all user-GUI alc_modes: OFF , and ALC modes .*/ +map.r.digital_filter_select_1.HPFAD = 1; // HPF1 ON (after ADC);page 40 datasheet, HPFAD bit controls the ON/OFF of the HPF1 (HPF ON is recommended). +map.r.digital_filter_select_1.HPFC = 0b11; // HPF Cut off frequency of high pass filter from 236.8 Hz @fs=48k ("00":3.7Hz, "01":14,8Hz, "10":118,4Hz) +update(Register::DigitalFilterSelect1); + +// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB., (not used by now , original code cond.) +// update(Register::RchMicGainSetting); // (those two lines , not activated, same as original) + +// pre-load 4 byes LPF coefficicients (.lpf_coefficient_0,1,2,3), FSA 14..0, FSB 14..0 , (fcut initial 6kHz, fs 48Khz). +// it will be default pre-loading coeff. for al ALC modes, LPF bit is activated down, for all ALC digital modes. +map.r.lpf_coefficient_0.l = 0x5F; // Pre-loading here LPF 6kHz, 1st Order from digital Block , Fc=6000 Hz, fs = 48khz +map.r.lpf_coefficient_1.h = 0x09; // LPF bit is activated down, for all ALC digital modes. +map.r.lpf_coefficient_2.l = 0xBF; // Writting reg to AK4951, with "update", following instructions. +map.r.lpf_coefficient_3.h = 0x32; + +update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0 +update(Register::LPFCoefficient1); // In this case , LPF 6KHz , when we activate the LPF block. +update(Register::LPFCoefficient2); +update(Register::LPFCoefficient3); + +// Reset , setting OFF all 5 x Digital Equalizer filters +map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled +map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled +map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled +map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled +map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled +update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp + + + if (alc_mode==0) { // Programmable Digital Filter OFF, same as original condition., no Digital ALC, nor Wind Noise Filter, LPF , EQ + + map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain. + update(Register::DigitalFilterSelect2); + + // Pre-loading AUDIO PATH with all DIGITAL BLOCK by pased, see, audio path block diagramm AK4951 datasheet + Table Playback mode -Recording mode. + // Digital filter block PATH is BY PASSED (we can swith off DIG. BLOCK power , PMPFIL=0) .The Path in Recording Mode 2 & Playback Mode 2 (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback) + map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode) + map.r.digital_filter_mode.PFSDO = 0; // ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block . + map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin) + update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode. + + map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management + map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management + map.r.power_management_1.PMPFIL = 0; // Pre-loading , Programmable Dig. filter OFF ,filter unused, routed around.(original value = 0 ) + update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used ) + + // 1059/fs, 22ms @ 48kHz + chThdSleepMilliseconds(22); + + } else { // ( alc_mode !=0) + + switch(alc_mode) { // Pre-loading register values depending on user-GUI selection (they will be sended below, with "update(Register_name::xxx )". + + case 1: // ALC-> on, (+12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + map.r.alc_mode_control_2.REF = 0xC0; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, C0H=+12dBs) + map.r.l_ch_input_volume_control.IV = 0xC0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0xC0; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REF’s + + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; + + case 2: // ALC-> on, (+09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + map.r.alc_mode_control_2.REF = 0xB8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B8H= +9dBs) + map.r.l_ch_input_volume_control.IV = 0xB8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0xB8; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REF’s + + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; + + case 3: // ALC-> on, (+06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + map.r.alc_mode_control_2.REF = 0xB0; // 0xB8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B0H= +6dBs) + map.r.l_ch_input_volume_control.IV = 0xB0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0xB0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s + + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; + + case 4: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original) + // + EQ boosting ~<2kHz (f0:1,1k, fb:1,7K, k=1,8) && + LPF 3,5k + map.r.alc_mode_control_2.REF = 0xA8; // 0xA8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs) + map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s + + //The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”. + map.r.digital_filter_select_3.EQ1 = 1; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled + update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp + + map.r.lpf_coefficient_0.l = 0x0D; // Pre-loading here LPF 3,5k , 1st Order from digital Block , Fc=3.500 Hz, fs = 48khz + map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes. + map.r.lpf_coefficient_2.l = 0x1A; // Writting reg to AK4951 , down with update.... + map.r.lpf_coefficient_3.h = 0x2C; + // LPF bit is activated down, for all ALC digital modes. + break; + + case 5: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original) + // + EQ boosting ~<3kHz (f0~1k4,fb~2,4k,k=1,8) && LPF 4kHz + map.r.alc_mode_control_2.REF = 0xA8; // 0xA0 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs) + map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s + + map.r.digital_filter_select_3.EQ2 = 1; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled + update(Register::DigitalFilterSelect3); + + map.r.lpf_coefficient_0.l = 0xC3; // Pre-loading here LPF 4k , 1st Order from digital Block , Fc=4000 Hz, fs = 48khz + map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes. + map.r.lpf_coefficient_2.l = 0x86; // Writting reg to AK4951 , down with update.... + map.r.lpf_coefficient_3.h = 0x2D; + // LPF bit is activated down, for all ALC digital modes. + break; + + case 6: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + map.r.alc_mode_control_2.REF = 0xA8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs) + map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s + + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; + + case 7: // ALC-> on, (+00dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + map.r.alc_mode_control_2.REF = 0xA0; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs) + map.r.l_ch_input_volume_control.IV = 0xA0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0xA0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s + + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; + + case 8: // ALC-> on, (-03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + map.r.alc_mode_control_2.REF = 0x98; //REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 98H=-03dBs) + map.r.l_ch_input_volume_control.IV = 0x98; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0x98; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s - const uint_fast8_t mgain = 0b0111; - map.r.signal_select_1.MGAIN20 = mgain & 7; - map.r.signal_select_1.PMMP = 1; - map.r.signal_select_1.MPSEL = 1; // MPWR2 pin - map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1; - update(Register::SignalSelect1); + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; - map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2 - map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2 - map.r.signal_select_2.MICL = 0; // MPWR = 2.4V - update(Register::SignalSelect2); + case 9: // ALC-> on, (-06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) + map.r.alc_mode_control_2.REF = 0x90; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 90H=-06dBs) + map.r.l_ch_input_volume_control.IV = 0x90; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0x90; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s -// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB. -// update(Register::RchMicGainSetting); -/* - map.r.timer_select.FRN = ?; - map.r.timer_select.FRATT = ?; - map.r.timer_select.ADRST = 0b??; - update(Register::TimerSelect); + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; - map.r.alc_timer_select. = ?; - update(Register::ALCTimerSelect); - map.r.alc_mode_control_1. = ?; - map.r.alc_mode_control_1.ALC = 1; + case 10: // ALC-> on, (-09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -3dB (18dB's) + // Reduce also Pre-amp Mic -3dB's (+18dB's) + mgain = 0b0110; // Pre-amp mic Mic Gain Pre-amp (+18dB), Original=0b0111 (+21dB's =7x3dBs), + + map.r.alc_mode_control_2.REF = 0x88; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 88H=-09dBs) + map.r.l_ch_input_volume_control.IV = 0x88; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0x88; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s + + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; + + case 11: // ALC-> on, (-12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -6dB (15dB's) + // Reduce also Pre-amp Mic -6dB's (+15dB's) + mgain = 0b0101; // Pre-amp mic Mic Gain Pre-amp (+15dB), (Original=0b0111 (+21dB's= 7x3dBs), + + map.r.alc_mode_control_2.REF = 0x80; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 80H=-12dBs) + map.r.l_ch_input_volume_control.IV = 0x80; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.r_ch_input_volume_control.IV = 0x80; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s + + // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz + // LPF bit is activated down, for all ALC digital modes. + break; + } + + //-------------------------------DIGITAL ALC (Automatic Level Control ) --- -------- + map.r.alc_mode_control_1.ALC = 0; // LMTH2-0, WTM1-0, RGAIN2-0, REF7-0, RFST1-0, EQFC1-0, FRATT, FRN and ALCEQN bits (needs to be set up with ALC disable = 0) update(Register::ALCModeControl1); - map.r.alc_mode_control_2.REF = ?; + map.r.timer_select.FRN = 0; // (FRN= 0 Fast Recovery mode , enable ) + map.r.timer_select.FRATT = 0; // Fast Recovery Ref. Volume Atten. Amount -0,00106dB's, timing 4/fs (default) + map.r.timer_select.ADRST = 0b00; // initial offset ADC cycles , 22ms @fs=48Khz. + update(Register::TimerSelect); + + map.r.alc_timer_select.RFST = 0b00; // RFST1-0: ALC Fast Recovery Speed Default: “00” (0.0032dB) + map.r.alc_timer_select.WTM = 0b00; // ALC Recovery Operation Waiting Period 128/fs = 2,7 mseg (min=default) + map.r.alc_timer_select.EQFC = 0b10; // Selecting default, fs 48Khz , ALCEQ: First order zero pole high pass filter fc2=100Hz, fc1=150Hz + map.r.alc_timer_select.IVTM = 0; // IVTM bit set the vol transition time ,236/fs = 4,9msecs (min) (default was 19,7msegs.) + update(Register::ALCTimerSelect); + + map.r.alc_mode_control_1.LMTH10 = 0b11; // ALC Limiter Detec Level/ Recovery Counter Reset; lower 2 bits (Ob111=-8,4dbs), (default 0b000=-2,5dBs) + map.r.alc_mode_control_1.RGAIN = 0b000; // ALC Recovery Gain Step, max step , max speed. Default: “000” (0.00424dB) + map.r.alc_mode_control_1.ALC = 1; // ALC Enable . (we are now, NOT in MANUAL volume mode, only becomes manual when (ALC=“0” while ADCPF=“1”. ) + map.r.alc_mode_control_1.LMTH2 = 1; // ALC Limiter Detection Level/ Recovery Counter Reset Level,Upper bit,default 0b000 + map.r.alc_mode_control_1.ALCEQN = 1; // ALC EQ Off =1 not used by now, 0: ALC EQ On (default) + update(Register::ALCModeControl1); + + // map.r.alc_mode_control_2.REF = 0x??; // Pre-loaded in top part. Maximum gain at ALC recovery operation,.(FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) update(Register::ALCModeControl2); -*/ -// map.r.l_ch_input_volume_control.IV = 0xe1; -// update(Register::LchInputVolumeControl); -// map.r.r_ch_input_volume_control.IV = 0xe1; -// update(Register::RchInputVolumeControl); -/* - map.r.auto_hpf_control.STG = 0b00; - map.r.auto_hpf_control.SENC = 0b011; - map.r.auto_hpf_control.AHPF = 0; - update(Register::AutoHPFControl); -*/ - map.r.digital_filter_select_1.HPFAD = 1; // HPF1 (after ADC) = on - map.r.digital_filter_select_1.HPFC = 0b11; // 2336.8 Hz @ fs=48k - update(Register::DigitalFilterSelect1); -/* - map.r.digital_filter_select_2.HPF = 0; - map.r.digital_filter_select_2.LPF = 0; - map.r.digital_filter_select_2.FIL3 = 0; - map.r.digital_filter_select_2.EQ0 = 0; - map.r.digital_filter_select_2.GN = 0b00; + + // map.r.l_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + update(Register::LchInputVolumeControl); + + // map.r.r_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Right,Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + update(Register::RchInputVolumeControl); + + + //---------------Switch ON, Digital Automatic Wind Noise Filter reduction ------------------- + // Difficult to realise that Dynamic HPF Wind noise filter benefit, maybe because we have another fixed HPF 236.8 Hz . + // Anyway , we propose to activate it , with default setting conditions. + map.r.power_management_1.PMPFIL = 0; // (*1) To programm SENC, STG , we need PMPFIL = 0 . (but this disconnect Digital block power supply. + update(Register::PowerManagement1); // Updated PMPFIL to 0 . (*1) + + map.r.auto_hpf_control.STG = 0b00; // (00=LOW ATTENUATION Level), lets put 11 (HIGH ATTENUATION Level) (default 00) + map.r.auto_hpf_control.SENC = 0b011; // (000=LOW sensitivity detection)… 111((MAX sensitivity detection) (default 011) + map.r.auto_hpf_control.AHPF = 1; // Autom. Wind noise filter ON (AHPF bit=“1”).It atten. wind noise when detecting ,and adjusts the atten. level dynamically. + update(Register::AutoHPFControl); + + // We are in Digital Block ON , (Wind Noise Filter+ALC+LPF+EQ),==> needs at the end , PMPFIL=1 , Program. Dig.filter ON + // map.r.power_management_1.PMPFIL = 1; // that instruction is at the end , we can skp pre-loading Programmable Dig. filter ON (*1) + //--------------------------------------------------------------------- + + // Writing AUDIO PATH diagramm, Changing Audio mode path : Playback mode1 /-Recording mode2. (Figure 37 AK4951 datasheet, Table 27. Recording Playback Mode) + // When changing those modes, PMPFIL bit must be “0”, it is OK (*1) + map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode) + map.r.digital_filter_mode.PFSDO = 1; // ADC (+ 1st order HPF) Output + map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin) + update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode. + + // The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”., but we are already (*1) + // map.r.power_management_1.PMPFIL = 0; // In the previous Wind Noise Filter , we already set up PPFIL = 0 + // update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used ) + + // ... Set EQ & LPF coefficients --------------------------------- + + // writting to the IC ak4951 reg. settings defined in Ak4951.hpp , the 30 bytes , EQ coefficient = 5 (EQ1,2,3,4,5) x 3 (A,B,C coefficients) x 2 bytes (16 bits) + update(Register::E1Coefficient0); // we could pre-load here,ex ,"map.r.e1_coefficient_0.l = 0x50;" , EQ1 Coefficient A : A7...A0, but already done in ak4951.hpp + update(Register::E1Coefficient1); // we could pre-load here,ex ,"map.r.e1_coefficient_1.h = 0xFE;" , EQ1 Coefficient A : A15..A8, " " + update(Register::E1Coefficient2); // we could pre-load here,ex ,"map.r.e1_coefficient_2.l = 0x29;" , EQ1 Coefficient B : B7...B0, " " + update(Register::E1Coefficient3); // we could pre-load here,ex ,"map.r.e1_coefficient_3.h = 0xC5;" , EQ1 Coefficient B : B15..B8, " " + update(Register::E1Coefficient4); // we could pre-load here,ex ,"map.r.e1_coefficient_4.l = 0xA0;" , EQ1 Coefficient C : C7...C0, " " + update(Register::E1Coefficient5); // we could pre-load here,ex ,"map.r.e1_coefficient_5.h = 0x1C;" , EQ1 Coefficient C : C15..C8, " " + + update(Register::E2Coefficient0); // writing pre-loaded EQ2 coefficcients + update(Register::E2Coefficient1); + update(Register::E2Coefficient2); + update(Register::E2Coefficient3); + update(Register::E2Coefficient4); + update(Register::E2Coefficient5); + + // Already pre-loaded LPF coefficients to 6k, 3,5k or 4k ,(LPF 6Khz all digital alc modes top , except when 3k5 , 4k) + update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0 + update(Register::LPFCoefficient1); + update(Register::LPFCoefficient2); + update(Register::LPFCoefficient3); + + // Activating LPF block , (and re-configuring the rest of bits of the same register) + map.r.digital_filter_select_2.HPF = 0; // HPF2-Block, Coeffic Setting Enable (OFF-Default), When HPF bit is “0”, audio data passes the HPF2 block by is 0dB gain. + map.r.digital_filter_select_2.LPF = 1; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain. + map.r.digital_filter_select_2.FIL3 = 0; // Stereo_Emphasis_Filter-Block,(OFF-Default) Coefficient Setting Enable , OFF , Disable. + map.r.digital_filter_select_2.EQ0 = 0; // Gain Compensation-Block, (OFF-Default) Coeffic Setting Enable, When EQ0 bit = “0” audio data passes the EQ0 block by 0dB gain. + map.r.digital_filter_select_2.GN = 0b00; // Gain Setting of the Gain Compensation Block Default: “00”-Default (0dB) update(Register::DigitalFilterSelect2); - map.r.digital_filter_select_3.EQ1 = 0; - map.r.digital_filter_select_3.EQ2 = 0; - map.r.digital_filter_select_3.EQ3 = 0; - map.r.digital_filter_select_3.EQ4 = 0; - map.r.digital_filter_select_3.EQ5 = 0; - update(Register::DigitalFilterSelect3); -*/ - map.r.digital_filter_mode.PFSDO = 0; // ADC (+ 1st order HPF) Output - map.r.digital_filter_mode.ADCPF = 1; // ADC Output (default) - update(Register::DigitalFilterMode); - - // ... Set coefficients ... - - map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal - map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal - map.r.power_management_1.PMPFIL = 0; // Programmable filter unused, routed around. - update(Register::PowerManagement1); + // Acitivating digital block , power supply + map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management + map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management + map.r.power_management_1.PMPFIL = 1; // Pre-loaded in top part. Orig value=0, Programmable Digital filter unused (not power up), routed around. + update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used ) // 1059/fs, 22ms @ 48kHz chThdSleepMilliseconds(22); + + } + + // Common part for all alc_mode , -------------------------- + // const uint_fast8_t mgain = 0b0111; // Already pre-loaded , in above switch case . + map.r.signal_select_1.MGAIN20 = mgain & 7; // writing 3 lower bits of mgain , (pre-amp mic gain). + map.r.signal_select_1.PMMP = 1; // Activating DC Mic Power supply through 2kohms res., similar majority smartphones headphone+mic jack, "plug-in-power" + map.r.signal_select_1.MPSEL = 1; // MPWR2 pin ,selecting output voltage to MPWR2 pin, that we are using in portapack ext. MIC) + map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1; // writing 4th upper bit of mgain (pre-amp mic gain). + update(Register::SignalSelect1); + } + + void AK4951::microphone_disable() { - map.r.power_management_1.PMADL = 0; - map.r.power_management_1.PMADR = 0; - map.r.power_management_1.PMPFIL = 0; + map.r.power_management_1.PMADL = 0; // original code , disable Power managem.Mic ADC L + map.r.power_management_1.PMADR = 0; // original code , disable Power managem.Mic ADC R + map.r.power_management_1.PMPFIL = 0; // original code , disable Power managem. all Programmable Dig. block update(Register::PowerManagement1); - map.r.alc_mode_control_1.ALC = 0; + map.r.alc_mode_control_1.ALC = 0; // original code , Restore , disable ALC block. update(Register::ALCModeControl1); + + map.r.auto_hpf_control.AHPF = 0; //----------- new code addition , Restore disable Wind noise filter OFF (AHPF bit=“0”). + update(Register::AutoHPFControl); + + //Restore original AUDIO PATH , condition, (Digital filter block PATH is BY PASSED) (we can also swith off DIG. BLOCK power , PMPFIL=0) + // The Path in Recording Mode 2 & Playback Mode 2 , (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback) + map.r.digital_filter_mode.ADCPF = 1; // new code addition , ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode) + map.r.digital_filter_mode.PFSDO = 0; // new code addition , ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block . + map.r.digital_filter_mode.PFDAC = 0b00; // new code addition , (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin) + update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode. + + // Restore original condition , LPF , OFF . same as when not using DIGITAL Programmable block + map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain. + update(Register::DigitalFilterSelect2); + + map.r.lpf_coefficient_0.l = 0x00; // Pre-loading here LPF 6k , 1st Order from digital Block , Fc=6000 Hz, fs = 48khz + map.r.lpf_coefficient_1.h = 0x00; // LPF bit is activated down, for all ALC digital modes. + map.r.lpf_coefficient_2.l = 0x00; // Writting reg to AK4951 , down with update.... + map.r.lpf_coefficient_3.h = 0x00; + + update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0 + update(Register::LPFCoefficient1); + update(Register::LPFCoefficient2); + update(Register::LPFCoefficient3); + + // Switch off all EQ 1,2,3,4,5 + map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled + map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled + map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled + map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled + map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled + update(Register::DigitalFilterSelect3); + } reg_t AK4951::read(const address_t reg_address) { diff --git a/firmware/common/ak4951.hpp b/firmware/common/ak4951.hpp index ab7d3b81..ea394966 100644 --- a/firmware/common/ak4951.hpp +++ b/firmware/common/ak4951.hpp @@ -773,40 +773,41 @@ constexpr RegisterMap default_after_reset { Register_Type { .REV = 0b1100, }, - .e1_coefficient_0 = { .l = 0x00 }, - .e1_coefficient_1 = { .h = 0x00 }, - .e1_coefficient_2 = { .l = 0x00 }, - .e1_coefficient_3 = { .h = 0x00 }, - .e1_coefficient_4 = { .l = 0x00 }, - .e1_coefficient_5 = { .h = 0x00 }, + // just pre-loading into memory, 30 bytes = EQ 1,2,3,4,5 x A,B,C (2 x bytes) coefficients, but it will be written from ak4951.cpp + .e1_coefficient_0 = { .l = 0xCA }, //EQ1 Coefficient A : A7...A0, BW : 300Hz - 1700Hz (fo = 1150Hz , fb= 1700Hz) , k=1,8 peaking + .e1_coefficient_1 = { .h = 0x05 }, //EQ1 Coefficient A : A15..A8 + .e1_coefficient_2 = { .l = 0xEB }, //EQ1 Coefficient B : B7...B0 + .e1_coefficient_3 = { .h = 0x38 }, //EQ1 Coefficient B : B15...B8 + .e1_coefficient_4 = { .l = 0x6F }, //EQ1 Coefficient C : C7...C0 + .e1_coefficient_5 = { .h = 0xE6 }, //EQ1 Coefficient C : C15..C8 - .e2_coefficient_0 = { .l = 0x00 }, - .e2_coefficient_1 = { .h = 0x00 }, - .e2_coefficient_2 = { .l = 0x00 }, - .e2_coefficient_3 = { .h = 0x00 }, - .e2_coefficient_4 = { .l = 0x00 }, - .e2_coefficient_5 = { .h = 0x00 }, + .e2_coefficient_0 = { .l = 0x05 }, //EQ2 Coefficient A : A7...A0, BW : 250Hz - 2700Hz (fo = 1475Hz , fb= 2450Hz) , k=1,8 peaking + .e2_coefficient_1 = { .h = 0x08 }, //EQ2 Coefficient A : A15..A8 + .e2_coefficient_2 = { .l = 0x11 }, //EQ2 Coefficient B : B7...B0 + .e2_coefficient_3 = { .h = 0x36 }, //EQ2 Coefficient B : B15...B8 + .e2_coefficient_4 = { .l = 0xE9 }, //EQ2 Coefficient C : C7...C0 + .e2_coefficient_5 = { .h = 0xE8 }, //EQ2 Coefficient C : C15..C8 - .e3_coefficient_0 = { .l = 0x00 }, - .e3_coefficient_1 = { .h = 0x00 }, - .e3_coefficient_2 = { .l = 0x00 }, - .e3_coefficient_3 = { .h = 0x00 }, - .e3_coefficient_4 = { .l = 0x00 }, - .e3_coefficient_5 = { .h = 0x00 }, + .e3_coefficient_0 = { .l = 0x00 }, //EQ3 Coefficient A : A7...A0, not used currently + .e3_coefficient_1 = { .h = 0x00 }, //EQ3 Coefficient A : A15..A8 + .e3_coefficient_2 = { .l = 0x00 }, //EQ3 Coefficient B : B7...B0 + .e3_coefficient_3 = { .h = 0x00 }, //EQ3 Coefficient B : B15...B8 + .e3_coefficient_4 = { .l = 0x00 }, //EQ3 Coefficient C : C7...C0 + .e3_coefficient_5 = { .h = 0x00 }, //EQ3 Coefficient C : C15..C8 - .e4_coefficient_0 = { .l = 0x00 }, - .e4_coefficient_1 = { .h = 0x00 }, - .e4_coefficient_2 = { .l = 0x00 }, - .e4_coefficient_3 = { .h = 0x00 }, - .e4_coefficient_4 = { .l = 0x00 }, - .e4_coefficient_5 = { .h = 0x00 }, + .e4_coefficient_0 = { .l = 0x00 }, //EQ4 Coefficient A : A7...A0, not used currently + .e4_coefficient_1 = { .h = 0x00 }, //EQ4 Coefficient A : A15..A8 + .e4_coefficient_2 = { .l = 0x00 }, //EQ4 Coefficient B : B7...B0 + .e4_coefficient_3 = { .h = 0x00 }, //EQ4 Coefficient B : B15...B8 + .e4_coefficient_4 = { .l = 0x00 }, //EQ4 Coefficient C : C7...C0 + .e4_coefficient_5 = { .h = 0x00 }, //EQ4 Coefficient C : C15..C8 - .e5_coefficient_0 = { .l = 0x00 }, - .e5_coefficient_1 = { .h = 0x00 }, - .e5_coefficient_2 = { .l = 0x00 }, - .e5_coefficient_3 = { .h = 0x00 }, - .e5_coefficient_4 = { .l = 0x00 }, - .e5_coefficient_5 = { .h = 0x00 }, + .e5_coefficient_0 = { .l = 0x00 }, //EQ5 Coefficient A : A7...A0, not used currently + .e5_coefficient_1 = { .h = 0x00 }, //EQ5 Coefficient A : A15..A8 + .e5_coefficient_2 = { .l = 0x00 }, //EQ5 Coefficient B : B7...B0 + .e5_coefficient_3 = { .h = 0x00 }, //EQ5 Coefficient B : B15...B8 + .e5_coefficient_4 = { .l = 0x00 }, //EQ5 Coefficient C : C7...C0 + .e5_coefficient_5 = { .h = 0x00 }, //EQ5 Coefficient C : C15..C8 } }; class AK4951 : public audio::Codec { @@ -839,7 +840,7 @@ public: void set_headphone_volume(const volume_t volume) override; void headphone_mute(); - void microphone_enable(); + void microphone_enable(int8_t alc_mode); // added user GUI parameter , to set up AK4951 ALC mode. void microphone_disable(); size_t reg_count() const override { diff --git a/firmware/common/wm8731.hpp b/firmware/common/wm8731.hpp index a5c8908b..ac164a04 100644 --- a/firmware/common/wm8731.hpp +++ b/firmware/common/wm8731.hpp @@ -345,8 +345,9 @@ public: void speaker_disable() {}; - void microphone_enable() override { - // TODO: Implement + void microphone_enable(int8_t alc_mode) override { + (void)alc_mode; // to avoid "unused warning" when compiling. (@WM8731 we do not use that parameter) + // TODO: Implement, } void microphone_disable() override { diff --git a/hackrf b/hackrf index 22267f3b..e6eb4ba2 160000 --- a/hackrf +++ b/hackrf @@ -1 +1 @@ -Subproject commit 22267f3b8e71bd064337921444b0e40509f47b43 +Subproject commit e6eb4ba29bbe5dc2fcd092e394188bc10a8bad54 From 9df1cfa670e103bc83536b96e1ceab5bdbc90fe5 Mon Sep 17 00:00:00 2001 From: jLynx Date: Wed, 23 Mar 2022 20:51:10 +1300 Subject: [PATCH 03/15] Added NZ to APRS --- firmware/application/apps/ui_aprs_rx.cpp | 3 +++ firmware/application/apps/ui_aprs_rx.hpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/firmware/application/apps/ui_aprs_rx.cpp b/firmware/application/apps/ui_aprs_rx.cpp index 6732e626..71e46fb2 100644 --- a/firmware/application/apps/ui_aprs_rx.cpp +++ b/firmware/application/apps/ui_aprs_rx.cpp @@ -115,6 +115,9 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect) : View(parent_rect if(i == 2){ field_frequency.set_value(145175000); } + if(i == 3){ + field_frequency.set_value(144575000); + } }; field_frequency.set_value(receiver_model.tuning_frequency()); diff --git a/firmware/application/apps/ui_aprs_rx.hpp b/firmware/application/apps/ui_aprs_rx.hpp index e392e62f..b7670e3d 100644 --- a/firmware/application/apps/ui_aprs_rx.hpp +++ b/firmware/application/apps/ui_aprs_rx.hpp @@ -217,7 +217,8 @@ private: { { "NA ", 0 }, { "EUR", 1 }, - { "AUS", 2 } + { "AUS", 2 }, + { "NZ", 3 } } }; From 1c81c7a8ba7d08124f48392418342d0edee8ef0a Mon Sep 17 00:00:00 2001 From: jLynx Date: Wed, 23 Mar 2022 21:32:32 +1300 Subject: [PATCH 04/15] Revert "Added NZ to APRS" This reverts commit 9df1cfa670e103bc83536b96e1ceab5bdbc90fe5. --- firmware/application/apps/ui_aprs_rx.cpp | 3 --- firmware/application/apps/ui_aprs_rx.hpp | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/firmware/application/apps/ui_aprs_rx.cpp b/firmware/application/apps/ui_aprs_rx.cpp index 71e46fb2..6732e626 100644 --- a/firmware/application/apps/ui_aprs_rx.cpp +++ b/firmware/application/apps/ui_aprs_rx.cpp @@ -115,9 +115,6 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect) : View(parent_rect if(i == 2){ field_frequency.set_value(145175000); } - if(i == 3){ - field_frequency.set_value(144575000); - } }; field_frequency.set_value(receiver_model.tuning_frequency()); diff --git a/firmware/application/apps/ui_aprs_rx.hpp b/firmware/application/apps/ui_aprs_rx.hpp index b7670e3d..e392e62f 100644 --- a/firmware/application/apps/ui_aprs_rx.hpp +++ b/firmware/application/apps/ui_aprs_rx.hpp @@ -217,8 +217,7 @@ private: { { "NA ", 0 }, { "EUR", 1 }, - { "AUS", 2 }, - { "NZ", 3 } + { "AUS", 2 } } }; From 0523aabe9112d3d44229a084426da9896059f7d9 Mon Sep 17 00:00:00 2001 From: jLynx Date: Thu, 24 Mar 2022 16:10:55 +1300 Subject: [PATCH 05/15] WIP PSI selector --- firmware/application/apps/tpms_app.cpp | 12 ++++++++++++ firmware/application/apps/tpms_app.hpp | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/firmware/application/apps/tpms_app.cpp b/firmware/application/apps/tpms_app.cpp index 82cdbd3f..62c04c8f 100644 --- a/firmware/application/apps/tpms_app.cpp +++ b/firmware/application/apps/tpms_app.cpp @@ -142,6 +142,7 @@ TPMSAppView::TPMSAppView(NavigationView&) { &field_rf_amp, &field_lna, &field_vga, + &options_type, &recent_entries_view, }); @@ -160,6 +161,17 @@ TPMSAppView::TPMSAppView(NavigationView&) { }; options_band.set_by_value(target_frequency()); + options_type.on_change = [this](size_t, int32_t i) { + if (i == 0){ + // field_frequency.set_value(144390000); + } + if(i == 1){ + // field_frequency.set_value(144800000); + } + }; + + options_type.set_selected_index(0, true); + logger = std::make_unique(); if( logger ) { logger->append(u"tpms.txt"); diff --git a/firmware/application/apps/tpms_app.hpp b/firmware/application/apps/tpms_app.hpp index ee17c6eb..993af22f 100644 --- a/firmware/application/apps/tpms_app.hpp +++ b/firmware/application/apps/tpms_app.hpp @@ -138,6 +138,15 @@ private: } }; + OptionsField options_type { + { 5 * 8, 0 * 16 }, + 3, + { + { "kPa", 0 }, + { "PSI", 1 } + } + }; + RFAmpField field_rf_amp { { 13 * 8, 0 * 16 } }; From 2030118d9fb18cccaa967a029713e6a98de62aad Mon Sep 17 00:00:00 2001 From: jLynx Date: Thu, 24 Mar 2022 17:05:38 +1300 Subject: [PATCH 06/15] WIP can now switch between kPa and PSI --- firmware/application/apps/tpms_app.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/firmware/application/apps/tpms_app.cpp b/firmware/application/apps/tpms_app.cpp index 62c04c8f..4d55bec0 100644 --- a/firmware/application/apps/tpms_app.cpp +++ b/firmware/application/apps/tpms_app.cpp @@ -34,6 +34,8 @@ namespace tpms { namespace format { +static bool use_kpa = true; + std::string type(Reading::Type type) { return to_string_dec_uint(toUType(type), 2); } @@ -43,7 +45,11 @@ std::string id(TransponderID id) { } std::string pressure(Pressure pressure) { - return to_string_dec_int(pressure.kilopascal(), 3); + if(use_kpa){ + return to_string_dec_int(pressure.kilopascal(), 3); + } + return to_string_dec_int(pressure.psi(), 3); + } std::string temperature(Temperature temperature) { @@ -163,10 +169,10 @@ TPMSAppView::TPMSAppView(NavigationView&) { options_type.on_change = [this](size_t, int32_t i) { if (i == 0){ - // field_frequency.set_value(144390000); + tpms::format::use_kpa = true; } if(i == 1){ - // field_frequency.set_value(144800000); + tpms::format::use_kpa = false; } }; From 32f957cead14ed051a807a98effb690f92fe694a Mon Sep 17 00:00:00 2001 From: jLynx Date: Thu, 24 Mar 2022 19:08:07 +1300 Subject: [PATCH 07/15] WIP updating header --- firmware/application/apps/tpms_app.cpp | 31 +++++++++++++++++++++----- firmware/application/apps/tpms_app.hpp | 10 +++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/firmware/application/apps/tpms_app.cpp b/firmware/application/apps/tpms_app.cpp index 4d55bec0..4362247e 100644 --- a/firmware/application/apps/tpms_app.cpp +++ b/firmware/application/apps/tpms_app.cpp @@ -149,9 +149,15 @@ TPMSAppView::TPMSAppView(NavigationView&) { &field_lna, &field_vga, &options_type, - &recent_entries_view, + // &recent_entries_view, + // &recent_entries_view_psi, }); + // remove_children({ + // &recent_entries_view, + // // &recent_entries_view_psi, + // }); + radio::enable({ tuning_frequency(), sampling_rate, @@ -169,10 +175,14 @@ TPMSAppView::TPMSAppView(NavigationView&) { options_type.on_change = [this](size_t, int32_t i) { if (i == 0){ - tpms::format::use_kpa = true; + tpms::format::use_kpa = true; + remove_child(&recent_entries_view_psi); + add_child(&recent_entries_view); } if(i == 1){ tpms::format::use_kpa = false; + remove_child(&recent_entries_view); + add_child(&recent_entries_view_psi); } }; @@ -197,6 +207,7 @@ void TPMSAppView::focus() { void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); recent_entries_view.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }); + recent_entries_view_psi.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }); } void TPMSAppView::on_packet(const tpms::Packet& packet) { @@ -209,13 +220,23 @@ void TPMSAppView::on_packet(const tpms::Packet& packet) { const auto reading = reading_opt.value(); auto& entry = ::on_packet(recent, TPMSRecentEntry::Key { reading.type(), reading.id() }); entry.update(reading); - recent_entries_view.set_dirty(); + + if(tpms::format::use_kpa){ + recent_entries_view.set_dirty(); + } else { + recent_entries_view_psi.set_dirty(); + } } } void TPMSAppView::on_show_list() { - recent_entries_view.hidden(false); - recent_entries_view.focus(); + if(tpms::format::use_kpa){ + recent_entries_view.hidden(false); + recent_entries_view.focus(); + } else { + recent_entries_view_psi.hidden(false); + recent_entries_view_psi.focus(); + } } void TPMSAppView::on_band_changed(const uint32_t new_band_frequency) { diff --git a/firmware/application/apps/tpms_app.hpp b/firmware/application/apps/tpms_app.hpp index 993af22f..55e70914 100644 --- a/firmware/application/apps/tpms_app.hpp +++ b/firmware/application/apps/tpms_app.hpp @@ -172,6 +172,16 @@ private: } }; TPMSRecentEntriesView recent_entries_view { columns, recent }; + const RecentEntriesColumns columns_psi { { + { "Tp", 2 }, + { "ID", 8 }, + { "PSI", 3 }, + { "C", 3 }, + { "Cnt", 3 }, + { "Fl", 2 }, + } }; + TPMSRecentEntriesView recent_entries_view_psi { columns_psi, recent }; + uint32_t target_frequency_ = initial_target_frequency; void on_packet(const tpms::Packet& packet); From 0025ad250718f0195340ee1acfddf460da812675 Mon Sep 17 00:00:00 2001 From: jLynx Date: Thu, 24 Mar 2022 19:19:02 +1300 Subject: [PATCH 08/15] refactoring --- firmware/application/apps/tpms_app.cpp | 42 +++++++++++--------------- firmware/application/apps/tpms_app.hpp | 4 +-- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/firmware/application/apps/tpms_app.cpp b/firmware/application/apps/tpms_app.cpp index 4362247e..d260d9b4 100644 --- a/firmware/application/apps/tpms_app.cpp +++ b/firmware/application/apps/tpms_app.cpp @@ -149,15 +149,8 @@ TPMSAppView::TPMSAppView(NavigationView&) { &field_lna, &field_vga, &options_type, - // &recent_entries_view, - // &recent_entries_view_psi, }); - // remove_children({ - // &recent_entries_view, - // // &recent_entries_view_psi, - // }); - radio::enable({ tuning_frequency(), sampling_rate, @@ -173,19 +166,6 @@ TPMSAppView::TPMSAppView(NavigationView&) { }; options_band.set_by_value(target_frequency()); - options_type.on_change = [this](size_t, int32_t i) { - if (i == 0){ - tpms::format::use_kpa = true; - remove_child(&recent_entries_view_psi); - add_child(&recent_entries_view); - } - if(i == 1){ - tpms::format::use_kpa = false; - remove_child(&recent_entries_view); - add_child(&recent_entries_view_psi); - } - }; - options_type.set_selected_index(0, true); logger = std::make_unique(); @@ -206,7 +186,21 @@ void TPMSAppView::focus() { void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); - recent_entries_view.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }); + + options_type.on_change = [this](size_t, int32_t i) { + if (i == 0){ + tpms::format::use_kpa = true; + remove_child(&recent_entries_view_psi); + add_child(&recent_entries_view_kpa); + } + if(i == 1){ + tpms::format::use_kpa = false; + remove_child(&recent_entries_view_kpa); + add_child(&recent_entries_view_psi); + } + }; + + recent_entries_view_kpa.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }); recent_entries_view_psi.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }); } @@ -222,7 +216,7 @@ void TPMSAppView::on_packet(const tpms::Packet& packet) { entry.update(reading); if(tpms::format::use_kpa){ - recent_entries_view.set_dirty(); + recent_entries_view_kpa.set_dirty(); } else { recent_entries_view_psi.set_dirty(); } @@ -231,8 +225,8 @@ void TPMSAppView::on_packet(const tpms::Packet& packet) { void TPMSAppView::on_show_list() { if(tpms::format::use_kpa){ - recent_entries_view.hidden(false); - recent_entries_view.focus(); + recent_entries_view_kpa.hidden(false); + recent_entries_view_kpa.focus(); } else { recent_entries_view_psi.hidden(false); recent_entries_view_psi.focus(); diff --git a/firmware/application/apps/tpms_app.hpp b/firmware/application/apps/tpms_app.hpp index 55e70914..44b4b15d 100644 --- a/firmware/application/apps/tpms_app.hpp +++ b/firmware/application/apps/tpms_app.hpp @@ -162,7 +162,7 @@ private: TPMSRecentEntries recent { }; std::unique_ptr logger { }; - const RecentEntriesColumns columns { { + const RecentEntriesColumns columns_kpa { { { "Tp", 2 }, { "ID", 8 }, { "kPa", 3 }, @@ -170,7 +170,7 @@ private: { "Cnt", 3 }, { "Fl", 2 }, } }; - TPMSRecentEntriesView recent_entries_view { columns, recent }; + TPMSRecentEntriesView recent_entries_view_kpa { columns_kpa, recent }; const RecentEntriesColumns columns_psi { { { "Tp", 2 }, From d1d1198b1b40da5bad845681f0991024fbfe49b9 Mon Sep 17 00:00:00 2001 From: jLynx Date: Thu, 24 Mar 2022 19:43:26 +1300 Subject: [PATCH 09/15] refactoring --- firmware/application/apps/tpms_app.cpp | 44 ++++++++++++++++++-------- firmware/application/apps/tpms_app.hpp | 3 ++ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/firmware/application/apps/tpms_app.cpp b/firmware/application/apps/tpms_app.cpp index d260d9b4..279c8a97 100644 --- a/firmware/application/apps/tpms_app.cpp +++ b/firmware/application/apps/tpms_app.cpp @@ -166,6 +166,22 @@ TPMSAppView::TPMSAppView(NavigationView&) { }; options_band.set_by_value(target_frequency()); + options_type.on_change = [this](size_t, int32_t i) { + if (i == 0){ + tpms::format::use_kpa = true; + // remove_child(&recent_entries_view_psi); + // add_child(&recent_entries_view_kpa); + // recent_entries_view_kpa.set_parent_rect(view_normal_rect); + } + if(i == 1){ + tpms::format::use_kpa = false; + // remove_child(&recent_entries_view_kpa); + // add_child(&recent_entries_view_psi); + // recent_entries_view_psi.set_parent_rect(view_normal_rect); + } + update_type(); + }; + options_type.set_selected_index(0, true); logger = std::make_unique(); @@ -184,24 +200,24 @@ void TPMSAppView::focus() { options_band.focus(); } +void TPMSAppView::update_type() { + if (tpms::format::use_kpa){ + remove_child(&recent_entries_view_psi); + add_child(&recent_entries_view_kpa); + recent_entries_view_kpa.set_parent_rect(view_normal_rect); + } else { + remove_child(&recent_entries_view_kpa); + add_child(&recent_entries_view_psi); + recent_entries_view_psi.set_parent_rect(view_normal_rect); + } +} + void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); - options_type.on_change = [this](size_t, int32_t i) { - if (i == 0){ - tpms::format::use_kpa = true; - remove_child(&recent_entries_view_psi); - add_child(&recent_entries_view_kpa); - } - if(i == 1){ - tpms::format::use_kpa = false; - remove_child(&recent_entries_view_kpa); - add_child(&recent_entries_view_psi); - } - }; + view_normal_rect = { 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }; - recent_entries_view_kpa.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }); - recent_entries_view_psi.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }); + update_type(); } void TPMSAppView::on_packet(const tpms::Packet& packet) { diff --git a/firmware/application/apps/tpms_app.hpp b/firmware/application/apps/tpms_app.hpp index 44b4b15d..648c5b49 100644 --- a/firmware/application/apps/tpms_app.hpp +++ b/firmware/application/apps/tpms_app.hpp @@ -121,6 +121,8 @@ private: static constexpr ui::Dim header_height = 1 * 16; + ui::Rect view_normal_rect { }; + RSSI rssi { { 21 * 8, 0, 6 * 8, 4 }, }; @@ -186,6 +188,7 @@ private: void on_packet(const tpms::Packet& packet); void on_show_list(); + void update_type(); void on_band_changed(const uint32_t new_band_frequency); From 165efd7355d7397fbc861bd36dae103d2b8558c4 Mon Sep 17 00:00:00 2001 From: jLynx Date: Thu, 24 Mar 2022 19:44:26 +1300 Subject: [PATCH 10/15] refactoring --- firmware/application/apps/tpms_app.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/firmware/application/apps/tpms_app.cpp b/firmware/application/apps/tpms_app.cpp index 279c8a97..750bc6e8 100644 --- a/firmware/application/apps/tpms_app.cpp +++ b/firmware/application/apps/tpms_app.cpp @@ -169,15 +169,9 @@ TPMSAppView::TPMSAppView(NavigationView&) { options_type.on_change = [this](size_t, int32_t i) { if (i == 0){ tpms::format::use_kpa = true; - // remove_child(&recent_entries_view_psi); - // add_child(&recent_entries_view_kpa); - // recent_entries_view_kpa.set_parent_rect(view_normal_rect); } if(i == 1){ tpms::format::use_kpa = false; - // remove_child(&recent_entries_view_kpa); - // add_child(&recent_entries_view_psi); - // recent_entries_view_psi.set_parent_rect(view_normal_rect); } update_type(); }; From 4a8458d812b7d8dcf9c01a1bb6c46be5dc7f0304 Mon Sep 17 00:00:00 2001 From: jLynx Date: Thu, 24 Mar 2022 19:51:08 +1300 Subject: [PATCH 11/15] refactoring --- firmware/application/apps/tpms_app.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/firmware/application/apps/tpms_app.cpp b/firmware/application/apps/tpms_app.cpp index 750bc6e8..7858d7a2 100644 --- a/firmware/application/apps/tpms_app.cpp +++ b/firmware/application/apps/tpms_app.cpp @@ -169,8 +169,7 @@ TPMSAppView::TPMSAppView(NavigationView&) { options_type.on_change = [this](size_t, int32_t i) { if (i == 0){ tpms::format::use_kpa = true; - } - if(i == 1){ + } else if (i == 1){ tpms::format::use_kpa = false; } update_type(); From 434c55986109f6d57b2f37a59f6a3d0010ce98ad Mon Sep 17 00:00:00 2001 From: notpike Date: Sat, 26 Mar 2022 21:20:49 -0700 Subject: [PATCH 12/15] Added Bias Tee support for Replay and fixed file error logic bug --- firmware/application/apps/replay_app.cpp | 11 ++++++++--- firmware/application/apps/ui_newapp.hpp | 0 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 firmware/application/apps/ui_newapp.hpp diff --git a/firmware/application/apps/replay_app.cpp b/firmware/application/apps/replay_app.cpp index 5b8d4a99..9d1f2acf 100644 --- a/firmware/application/apps/replay_app.cpp +++ b/firmware/application/apps/replay_app.cpp @@ -97,6 +97,7 @@ void ReplayAppView::focus() { } void ReplayAppView::file_error() { + //stop(false); // Fixes TX bug if there's a file error nav_.display_modal("Error", "File read error."); } @@ -121,6 +122,7 @@ void ReplayAppView::start() { auto open_error = p->open(file_path); if( open_error.is_valid() ) { file_error(); + return; // Fixes TX bug if there's a file error } else { reader = std::move(p); } @@ -150,17 +152,19 @@ void ReplayAppView::start() { rf_amp = (bool)v; }; field_rfamp.set_value(rf_amp ? 14 : 0); + + //Enable Bias Tee if selected + radio::set_antenna_bias(portapack::get_antenna_bias()); radio::enable({ receiver_model.tuning_frequency(), - sample_rate * 8 , + sample_rate * 8, baseband_bandwidth, rf::Direction::Transmit, rf_amp, // previous code line : "receiver_model.rf_amp()," was passing the same rf_amp of all Receiver Apps static_cast(receiver_model.lna()), static_cast(receiver_model.vga()) - }); - + }); } void ReplayAppView::stop(const bool do_loop) { @@ -170,6 +174,7 @@ void ReplayAppView::stop(const bool do_loop) { if (do_loop && check_loop.value()) { start(); } else { + radio::set_antenna_bias(false); //Turn off Bias Tee radio::disable(); button_play.set_bitmap(&bitmap_play); } diff --git a/firmware/application/apps/ui_newapp.hpp b/firmware/application/apps/ui_newapp.hpp new file mode 100644 index 00000000..e69de29b From 4ef98e2928b1d60005c5db6d008eaa739d0f09ce Mon Sep 17 00:00:00 2001 From: notpike Date: Sat, 26 Mar 2022 21:20:55 -0700 Subject: [PATCH 13/15] Added Bias Tee support for Replay and fixed file error logic bug --- firmware/application/apps/replay_app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/apps/replay_app.cpp b/firmware/application/apps/replay_app.cpp index 9d1f2acf..9147c46f 100644 --- a/firmware/application/apps/replay_app.cpp +++ b/firmware/application/apps/replay_app.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2016 Furrtek + * Copyleft (ↄ) 2022 NotPike * * This file is part of PortaPack. * @@ -97,7 +98,6 @@ void ReplayAppView::focus() { } void ReplayAppView::file_error() { - //stop(false); // Fixes TX bug if there's a file error nav_.display_modal("Error", "File read error."); } From 37a40cbedad4cc95c0c7613f4e5017447b71e494 Mon Sep 17 00:00:00 2001 From: NotPike <18655435+notpike@users.noreply.github.com> Date: Sun, 27 Mar 2022 00:40:45 -0400 Subject: [PATCH 14/15] Delete ui_newapp.hpp --- firmware/application/apps/ui_newapp.hpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 firmware/application/apps/ui_newapp.hpp diff --git a/firmware/application/apps/ui_newapp.hpp b/firmware/application/apps/ui_newapp.hpp deleted file mode 100644 index e69de29b..00000000 From be0427889ffc79776f497e4d83640a72af3339ad Mon Sep 17 00:00:00 2001 From: Arjan Onwezen Date: Sat, 26 Mar 2022 07:05:13 -0400 Subject: [PATCH 15/15] Added country to AIS app, so you know from which country a vessel is. It's using the MID database, which is also part of the PR. mids.db should be placed in /AIS folder on SD card. --- firmware/application/apps/ais_app.cpp | 21 ++ firmware/application/apps/ais_app.hpp | 5 +- firmware/application/database.cpp | 10 + firmware/application/database.hpp | 6 + .../MaritimeIdentificationDigits.csv | 295 ++++++++++++++++++ firmware/tools/make_mids_db/README.md | 13 + firmware/tools/make_mids_db/make_mid_db.py | 55 ++++ firmware/tools/make_mids_db/mids.db | Bin 0 -> 10584 bytes sdcard/AIS/mids.db | Bin 0 -> 10584 bytes 9 files changed, 403 insertions(+), 2 deletions(-) create mode 100755 firmware/tools/make_mids_db/MaritimeIdentificationDigits.csv create mode 100644 firmware/tools/make_mids_db/README.md create mode 100755 firmware/tools/make_mids_db/make_mid_db.py create mode 100644 firmware/tools/make_mids_db/mids.db create mode 100644 sdcard/AIS/mids.db diff --git a/firmware/application/apps/ais_app.cpp b/firmware/application/apps/ais_app.cpp index ee7527c3..06a36a6f 100644 --- a/firmware/application/apps/ais_app.cpp +++ b/firmware/application/apps/ais_app.cpp @@ -22,6 +22,7 @@ #include "ais_app.hpp" #include "string_format.hpp" +#include "database.hpp" #include "baseband_api.hpp" @@ -62,6 +63,25 @@ static std::string mmsi( return to_string_dec_uint(mmsi, 9, '0'); // MMSI is always is always 9 characters pre-padded with zeros } + +static std::string mid( + const ais::MMSI& mmsi +) { + std::database db; + std::string mid_code = ""; + std::database::MidDBRecord mid_record = {}; + int return_code = 0; + + // Try getting the country name from mids.db using MID code for given MMSI + mid_code = to_string_dec_uint(mmsi, 9, ' ').substr(0, 3); + return_code = db.retrieve_mid_record(&mid_record, mid_code); + switch(return_code) { + case DATABASE_RECORD_FOUND: return mid_record.country; + case DATABASE_NOT_FOUND: return "No mids.db file"; + default: return ""; + } +} + static std::string navigational_status(const unsigned int value) { switch(value) { case 0: return "under way w/engine"; @@ -271,6 +291,7 @@ void AISRecentEntryDetailView::paint(Painter& painter) { auto field_rect = Rect { rect.left(), rect.top() + 16, rect.width(), 16 }; field_rect = draw_field(painter, field_rect, s, "MMSI", ais::format::mmsi(entry_.mmsi)); + field_rect = draw_field(painter, field_rect, s, "Ctry", ais::format::mid(entry_.mmsi)); field_rect = draw_field(painter, field_rect, s, "Name", entry_.name); field_rect = draw_field(painter, field_rect, s, "Call", entry_.call_sign); field_rect = draw_field(painter, field_rect, s, "Dest", entry_.destination); diff --git a/firmware/application/apps/ais_app.hpp b/firmware/application/apps/ais_app.hpp index e0093d8b..c7f03aca 100644 --- a/firmware/application/apps/ais_app.hpp +++ b/firmware/application/apps/ais_app.hpp @@ -131,11 +131,11 @@ private: AISRecentEntry entry_ { }; Button button_done { - { 125, 216, 96, 24 }, + { 125, 224, 96, 24 }, "Done" }; Button button_see_map { - { 19, 216, 96, 24 }, + { 19, 224, 96, 24 }, "See on map" }; GeoMapView* geomap_view { nullptr }; @@ -169,6 +169,7 @@ private: static constexpr uint32_t initial_target_frequency = 162025000; static constexpr uint32_t sampling_rate = 2457600; static constexpr uint32_t baseband_bandwidth = 1750000; + NavigationView& nav_; AISRecentEntries recent { }; diff --git a/firmware/application/database.cpp b/firmware/application/database.cpp index edac3ef7..54bc1de4 100644 --- a/firmware/application/database.cpp +++ b/firmware/application/database.cpp @@ -27,6 +27,16 @@ namespace std { +int database::retrieve_mid_record(MidDBRecord* record, std::string search_term){ + + file_path = "AIS/mids.db"; + index_item_length = 4; + record_length = 32; + + result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term); + + return(result); +} int database::retrieve_airline_record(AirlinesDBRecord* record, std::string search_term){ diff --git a/firmware/application/database.hpp b/firmware/application/database.hpp index 7159f6b1..9dee1a61 100644 --- a/firmware/application/database.hpp +++ b/firmware/application/database.hpp @@ -44,6 +44,12 @@ public: #define DATABASE_NOT_FOUND -1 // database not found / could not be opened #define DATABASE_RECORD_NOT_FOUND -2 // record could not be found in database + struct MidDBRecord { + char country[32]; // country name + }; + + int retrieve_mid_record(MidDBRecord* record, std::string search_term); + struct AirlinesDBRecord { char airline[32]; // airline name char country[32]; // country name diff --git a/firmware/tools/make_mids_db/MaritimeIdentificationDigits.csv b/firmware/tools/make_mids_db/MaritimeIdentificationDigits.csv new file mode 100755 index 00000000..744218e7 --- /dev/null +++ b/firmware/tools/make_mids_db/MaritimeIdentificationDigits.csv @@ -0,0 +1,295 @@ +Digit,Allocated to +201,Albania (Republic of) +202,Andorra (Principality of) +203,Austria +204,Portugal - Azores +205,Belgium +206,Belarus (Republic of) +207,Bulgaria (Republic of) +208,Vatican City State +209,Cyprus (Republic of) +210,Cyprus (Republic of) +211,Germany (Federal Republic of) +212,Cyprus (Republic of) +213,Georgia +214,Moldova (Republic of) +215,Malta +216,Armenia (Republic of) +218,Germany (Federal Republic of) +219,Denmark +220,Denmark +224,Spain +225,Spain +226,France +227,France +228,France +229,Malta +230,Finland +231,Denmark - Faroe Islands +232,United Kingdom of Great Britain and Northern Ireland +233,United Kingdom of Great Britain and Northern Ireland +234,United Kingdom of Great Britain and Northern Ireland +235,United Kingdom of Great Britain and Northern Ireland +236,United Kingdom of Great Britain and Northern Ireland - Gibraltar +237,Greece +238,Croatia (Republic of) +239,Greece +240,Greece +241,Greece +242,Morocco (Kingdom of) +243,Hungary +244,Netherlands (Kingdom of the) +245,Netherlands (Kingdom of the) +246,Netherlands (Kingdom of the) +247,Italy +248,Malta +249,Malta +250,Ireland +251,Iceland +252,Liechtenstein (Principality of) +253,Luxembourg +254,Monaco (Principality of) +255,Portugal - Madeira +256,Malta +257,Norway +258,Norway +259,Norway +261,Poland (Republic of) +262,Montenegro +263,Portugal +264,Romania +265,Sweden +266,Sweden +267,Slovak Republic +268,San Marino (Republic of) +269,Switzerland (Confederation of) +270,Czech Republic +271,Turkey +272,Ukraine +273,Russian Federation +274,North Macedonia (Republic of) +275,Latvia (Republic of) +276,Estonia (Republic of) +277,Lithuania (Republic of) +278,Slovenia (Republic of) +279,Serbia (Republic of) +301,United Kingdom of Great Britain and Northern Ireland - Anguilla +303,United States of America - Alaska (State of) +304,Antigua and Barbuda +305,Antigua and Barbuda +306,"Netherlands (Kingdom of the) - Bonaire, Sint Eustatius and Saba" +306,Netherlands (Kingdom of the) - Curaçao +306,Netherlands (Kingdom of the) - Sint Maarten (Dutch part) +307,Netherlands (Kingdom of the) - Aruba +308,Bahamas (Commonwealth of the) +309,Bahamas (Commonwealth of the) +310,United Kingdom of Great Britain and Northern Ireland - Bermuda +311,Bahamas (Commonwealth of the) +312,Belize +314,Barbados +316,Canada +319,United Kingdom of Great Britain and Northern Ireland - Cayman Islands +321,Costa Rica +323,Cuba +325,Dominica (Commonwealth of) +327,Dominican Republic +329,France - Guadeloupe (French Department of) +330,Grenada +331,Denmark - Greenland +332,Guatemala (Republic of) +334,Honduras (Republic of) +336,Haiti (Republic of) +338,United States of America +339,Jamaica +341,Saint Kitts and Nevis (Federation of) +343,Saint Lucia +345,Mexico +347,France - Martinique (French Department of) +348,United Kingdom of Great Britain and Northern Ireland - Montserrat +350,Nicaragua +351,Panama (Republic of) +352,Panama (Republic of) +353,Panama (Republic of) +354,Panama (Republic of) +355,Panama (Republic of) +356,Panama (Republic of) +357,Panama (Republic of) +358,United States of America - Puerto Rico +359,El Salvador (Republic of) +361,France - Saint Pierre and Miquelon (Territorial Collectivity of) +362,Trinidad and Tobago +364,United Kingdom of Great Britain and Northern Ireland - Turks and Caicos Islands +366,United States of America +367,United States of America +368,United States of America +369,United States of America +370,Panama (Republic of) +371,Panama (Republic of) +372,Panama (Republic of) +373,Panama (Republic of) +374,Panama (Republic of) +375,Saint Vincent and the Grenadines +376,Saint Vincent and the Grenadines +377,Saint Vincent and the Grenadines +378,United Kingdom of Great Britain and Northern Ireland - British Virgin Islands +379,United States of America - United States Virgin Islands +401,Afghanistan +403,Saudi Arabia (Kingdom of) +405,Bangladesh (People's Republic of) +408,Bahrain (Kingdom of) +410,Bhutan (Kingdom of) +412,China (People's Republic of) +413,China (People's Republic of) +414,China (People's Republic of) +416,China (People's Republic of) - Taiwan (Province of China) +417,Sri Lanka (Democratic Socialist Republic of) +419,India (Republic of) +422,Iran (Islamic Republic of) +423,Azerbaijan (Republic of) +425,Iraq (Republic of) +428,Israel (State of) +431,Japan +432,Japan +434,Turkmenistan +436,Kazakhstan (Republic of) +437,Uzbekistan (Republic of) +438,Jordan (Hashemite Kingdom of) +440,Korea (Republic of) +441,Korea (Republic of) +443,"State of Palestine (In accordance with Resolution 99 Rev. Dubai, 2018)" +445,Democratic People's Republic of Korea +447,Kuwait (State of) +450,Lebanon +451,Kyrgyz Republic +453,China (People's Republic of) - Macao (Special Administrative Region of China) +455,Maldives (Republic of) +457,Mongolia +459,Nepal (Federal Democratic Republic of) +461,Oman (Sultanate of) +463,Pakistan (Islamic Republic of) +466,Qatar (State of) +468,Syrian Arab Republic +470,United Arab Emirates +471,United Arab Emirates +472,Tajikistan (Republic of) +473,Yemen (Republic of) +475,Yemen (Republic of) +477,China (People's Republic of) - Hong Kong (Special Administrative Region of China) +478,Bosnia and Herzegovina +501,France - Adelie Land +503,Australia +506,Myanmar (Union of) +508,Brunei Darussalam +510,Micronesia (Federated States of) +511,Palau (Republic of) +512,New Zealand +514,Cambodia (Kingdom of) +515,Cambodia (Kingdom of) +516,Australia - Christmas Island (Indian Ocean) +518,New Zealand - Cook Islands +520,Fiji (Republic of) +523,Australia - Cocos (Keeling) Islands +525,Indonesia (Republic of) +529,Kiribati (Republic of) +531,Lao People's Democratic Republic +533,Malaysia +536,United States of America - Northern Mariana Islands (Commonwealth of the) +538,Marshall Islands (Republic of the) +540,France - New Caledonia +542,New Zealand - Niue +544,Nauru (Republic of) +546,France - French Polynesia +548,Philippines (Republic of the) +550,Timor-Leste (Democratic Republic of) +553,Papua New Guinea +555,United Kingdom of Great Britain and Northern Ireland - Pitcairn Island +557,Solomon Islands +559,United States of America - American Samoa +561,Samoa (Independent State of) +563,Singapore (Republic of) +564,Singapore (Republic of) +565,Singapore (Republic of) +566,Singapore (Republic of) +567,Thailand +570,Tonga (Kingdom of) +572,Tuvalu +574,Viet Nam (Socialist Republic of) +576,Vanuatu (Republic of) +577,Vanuatu (Republic of) +578,France - Wallis and Futuna Islands +601,South Africa (Republic of) +603,Angola (Republic of) +605,Algeria (People's Democratic Republic of) +607,France - Saint Paul and Amsterdam Islands +608,United Kingdom of Great Britain and Northern Ireland - Ascension Island +609,Burundi (Republic of) +610,Benin (Republic of) +611,Botswana (Republic of) +612,Central African Republic +613,Cameroon (Republic of) +615,Congo (Republic of the) +616,Comoros (Union of the) +617,Cabo Verde (Republic of) +618,France - Crozet Archipelago +619,Côte d'Ivoire (Republic of) +620,Comoros (Union of the) +621,Djibouti (Republic of) +622,Egypt (Arab Republic of) +624,Ethiopia (Federal Democratic Republic of) +625,Eritrea +626,Gabonese Republic +627,Ghana +629,Gambia (Republic of the) +630,Guinea-Bissau (Republic of) +631,Equatorial Guinea (Republic of) +632,Guinea (Republic of) +633,Burkina Faso +634,Kenya (Republic of) +635,France - Kerguelen Islands +636,Liberia (Republic of) +637,Liberia (Republic of) +638,South Sudan (Republic of) +642,Libya (State of) +644,Lesotho (Kingdom of) +645,Mauritius (Republic of) +647,Madagascar (Republic of) +649,Mali (Republic of) +650,Mozambique (Republic of) +654,Mauritania (Islamic Republic of) +655,Malawi +656,Niger (Republic of the) +657,Nigeria (Federal Republic of) +659,Namibia (Republic of) +660,France - Reunion (French Department of) +661,Rwanda (Republic of) +662,Sudan (Republic of the) +663,Senegal (Republic of) +664,Seychelles (Republic of) +665,United Kingdom of Great Britain and Northern Ireland - Saint Helena +666,Somalia (Federal Republic of) +667,Sierra Leone +668,Sao Tome and Principe (Democratic Republic of) +669,Eswatini (Kingdom of) +670,Chad (Republic of) +671,Togolese Republic +672,Tunisia +674,Tanzania (United Republic of) +675,Uganda (Republic of) +676,Democratic Republic of the Congo +677,Tanzania (United Republic of) +678,Zambia (Republic of) +679,Zimbabwe (Republic of) +701,Argentine Republic +710,Brazil (Federative Republic of) +720,Bolivia (Plurinational State of) +725,Chile +730,Colombia (Republic of) +735,Ecuador +740,United Kingdom of Great Britain and Northern Ireland - Falkland Islands (Malvinas) +745,France - Guiana (French Department of) +750,Guyana +755,Paraguay (Republic of) +760,Peru +765,Suriname (Republic of) +770,Uruguay (Eastern Republic of) +775,Venezuela (Bolivarian Republic of) diff --git a/firmware/tools/make_mids_db/README.md b/firmware/tools/make_mids_db/README.md new file mode 100644 index 00000000..f99ced74 --- /dev/null +++ b/firmware/tools/make_mids_db/README.md @@ -0,0 +1,13 @@ +# Make mids.db + +Licensed under [GNU GPL v3](../../../LICENSE) + +Python3 script creates a MID (Marine Identification Digit) database. +MID is part of MMSI and determines (among other things) the conutry. + + +USAGE: + - Copy Excel file from https://www.itu.int/en/ITU-R/terrestrial/fmd/Pages/mid.aspx + - Convert it to a csv document + - Run Python 3 script: `./make_mids_db.py` + - Copy file to /AIS folder on SDCARD diff --git a/firmware/tools/make_mids_db/make_mid_db.py b/firmware/tools/make_mids_db/make_mid_db.py new file mode 100755 index 00000000..43615887 --- /dev/null +++ b/firmware/tools/make_mids_db/make_mid_db.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2022 ArjanOnwezen +# +# 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 +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +# ------------------------------------------------------------------------------------- +# Create mids.db, used for AIS receiver application, using converted Excel file on page: +# https://www.itu.int/en/ITU-R/terrestrial/fmd/Pages/mid.aspx +# as a source. +# MID stands for Marine Identification Digits and can be used to determine conutry of +# vessel or coastal station. +# ------------------------------------------------------------------------------------- +import csv +import re +import unicodedata +mid_codes=bytearray() +countries=bytearray() +row_count=0 + +database=open("mids.db", "wb") + +with open('MaritimeIdentificationDigits.csv', 'rt') as csv_file: + sorted_lines=sorted(csv_file.readlines()) + + for row in csv.reader(sorted_lines, quotechar='"', delimiter=',', quoting=csv.QUOTE_ALL, skipinitialspace=True): + mid_code=row[0] + # Normalize some unicode characters +#unicodedata.normalize('NFKD', row[3][:32]).encode('ascii', 'ignore') + country=unicodedata.normalize('NFKD', "".join(re.split("\(|\)|\[|\]", row[1].split('-')[-1].replace(" of Great Britain and Northern Ireland" , ""))[::2])).replace("Democratic People's Republic of Korea", "North-Korea").strip().encode('ascii', 'ignore')[:32] + if len(mid_code) == 3 : + country_padding=bytearray() + print(mid_code,' - ', country) + mid_codes=mid_codes+bytearray(mid_code+'\0', encoding='ascii') + country_padding=bytearray('\0' * (32 - len(country)), encoding='ascii') + countries=countries+country+country_padding + row_count+=1 + +database.write(mid_codes+countries) +print("Total of", row_count, "MID codes stored in database") + diff --git a/firmware/tools/make_mids_db/mids.db b/firmware/tools/make_mids_db/mids.db new file mode 100644 index 0000000000000000000000000000000000000000..82f6373dab0abb252502ebbab5b08e4c6e3d0188 GIT binary patch literal 10584 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 bNO+^e9W=pL-_RTnPM