2022-11-02 18:23:41 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "SinglePortModule.h"
|
|
|
|
|
#include "concurrency/OSThread.h"
|
|
|
|
|
#include "configuration.h"
|
|
|
|
|
#include "NodeDB.h"
|
|
|
|
|
#include <Arduino.h>
|
|
|
|
|
#include <driver/adc.h>
|
|
|
|
|
#include <functional>
|
2022-11-29 11:22:18 +01:00
|
|
|
#if defined(ARCH_ESP32)
|
2022-11-02 18:23:41 +01:00
|
|
|
#include <codec2.h>
|
|
|
|
|
#include <ButterworthFilter.h>
|
|
|
|
|
#include <FastAudioFIFO.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define ADC_BUFFER_SIZE 320 // 40ms of voice in 8KHz sampling frequency
|
2022-11-29 11:22:18 +01:00
|
|
|
#define ENCODE_CODEC2_SIZE 8
|
|
|
|
|
#define ENCODE_FRAME_SIZE (ENCODE_CODEC2_SIZE * 5) // 5 codec2 frames of 8 bytes each
|
|
|
|
|
|
|
|
|
|
class Codec2Thread : public concurrency::NotifiedWorkerThread
|
|
|
|
|
{
|
|
|
|
|
#if defined(ARCH_ESP32)
|
|
|
|
|
struct CODEC2* codec2_state = NULL;
|
|
|
|
|
int16_t output_buffer[ADC_BUFFER_SIZE] = {};
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Codec2Thread();
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual void onNotify(uint32_t notification) override;
|
|
|
|
|
#endif
|
|
|
|
|
};
|
2022-11-02 18:23:41 +01:00
|
|
|
|
|
|
|
|
class AudioModule : public SinglePortModule, private concurrency::OSThread
|
|
|
|
|
{
|
2022-11-29 11:22:18 +01:00
|
|
|
#if defined(ARCH_ESP32)
|
|
|
|
|
bool firstTime = true;
|
2022-11-02 18:23:41 +01:00
|
|
|
hw_timer_t* adcTimer = NULL;
|
2022-11-29 11:22:18 +01:00
|
|
|
|
2022-11-02 18:23:41 +01:00
|
|
|
FastAudioFIFO audio_fifo;
|
|
|
|
|
uint16_t adc_buffer_index = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
2022-11-29 11:22:18 +01:00
|
|
|
unsigned char rx_encode_frame[ENCODE_FRAME_SIZE] = {};
|
|
|
|
|
unsigned char tx_encode_frame[ENCODE_FRAME_SIZE] = {};
|
|
|
|
|
int tx_encode_frame_index = 0;
|
|
|
|
|
|
2022-11-02 18:23:41 +01:00
|
|
|
AudioModule();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send our payload into the mesh
|
|
|
|
|
*/
|
|
|
|
|
void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual int32_t runOnce() override;
|
|
|
|
|
|
2022-11-29 11:22:18 +01:00
|
|
|
// void run_codec2();
|
2022-11-02 18:23:41 +01:00
|
|
|
|
|
|
|
|
virtual MeshPacket *allocReply() override;
|
|
|
|
|
|
|
|
|
|
/** Called to handle a particular incoming message
|
|
|
|
|
* @return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for it
|
|
|
|
|
*/
|
|
|
|
|
virtual ProcessMessage handleReceived(const MeshPacket &mp) override;
|
2022-11-06 13:29:01 +01:00
|
|
|
#endif
|
2022-11-02 18:23:41 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern AudioModule *audioModule;
|
2022-11-29 11:22:18 +01:00
|
|
|
extern Codec2Thread *codec2Thread;
|
|
|
|
|
|
|
|
|
|
extern FastAudioFIFO audio_fifo;
|
|
|
|
|
extern uint16_t adc_buffer[ADC_BUFFER_SIZE];
|
|
|
|
|
extern uint16_t adc_buffer_index;
|
|
|
|
|
extern portMUX_TYPE timerMux;
|
|
|
|
|
extern int16_t speech[ADC_BUFFER_SIZE];
|
|
|
|
|
enum RadioState { standby, rx, tx };
|
|
|
|
|
extern volatile RadioState radio_state;
|
|
|
|
|
extern adc1_channel_t mic_chan;
|
|
|
|
|
|
|
|
|
|
IRAM_ATTR void am_onTimer();
|
2022-11-02 18:23:41 +01:00
|
|
|
|