diff --git a/platform/drivers/baseband/AT1846S_UV3x0.c b/platform/drivers/baseband/AT1846S_UV3x0.c
new file mode 100644
index 00000000..38792dc6
--- /dev/null
+++ b/platform/drivers/baseband/AT1846S_UV3x0.c
@@ -0,0 +1,294 @@
+/***************************************************************************
+ *   Copyright (C) 2020 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  *
+ *   the Free Software Foundation; either version 3 of the License, 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; if not, see <http://www.gnu.org/licenses/>   *
+ ***************************************************************************/
+
+#include <interfaces/delays.h>
+#include "interfaces.h"
+#include "AT1846S.h"
+
+void _maskSetRegister(uint8_t reg, uint16_t mask, uint16_t value)
+{
+    uint16_t regVal = i2c_readReg16(reg);
+    regVal = (regVal & ~mask) | (value & mask);
+    i2c_writeReg16(reg, regVal);
+}
+
+/*
+ * NOTE: after some main AT1846S parameters (frequency, bandwidth, ...) are changed,
+ * the chip must be "cycled" to make them effective. Cycling consists of turning
+ * both TX and RX off and then switch back to the desired functionality.
+ *
+ * The function _reloadConfig() provides an helper to do this.
+ */
+static inline void _reloadConfig()
+{
+    uint16_t reg = i2c_readReg16(0x30);    /* Get current op. status */
+    i2c_writeReg16(0x30, reg & 0xFF9F);    /* RX and TX off          */
+    i2c_writeReg16(0x30, reg);             /* Restore op. status     */
+}
+
+
+void AT1846S_init()
+{
+    i2c_writeReg16(0x30, 0x0001);   /* Soft reset              */
+    delayMs(100);
+
+    i2c_writeReg16(0x30, 0x0004);
+
+    i2c_writeReg16(0x04, 0x0FD0);
+    i2c_writeReg16(0x0A, 0x7C20);
+    i2c_writeReg16(0x13, 0xA100);
+    i2c_writeReg16(0x1F, 0x1001);
+    i2c_writeReg16(0x31, 0x0031);
+    i2c_writeReg16(0x33, 0x44A5);
+    i2c_writeReg16(0x34, 0x2B89);
+    i2c_writeReg16(0x41, 0x4122);
+    i2c_writeReg16(0x42, 0x1052);
+    i2c_writeReg16(0x43, 0x0100);
+    i2c_writeReg16(0x44, 0x07FF);
+    i2c_writeReg16(0x59, 0x0B90);
+    i2c_writeReg16(0x47, 0x7F2F);
+    i2c_writeReg16(0x4F, 0x2C62);
+    i2c_writeReg16(0x53, 0x0094);
+    i2c_writeReg16(0x54, 0x2A3C);
+    i2c_writeReg16(0x55, 0x0081);
+    i2c_writeReg16(0x56, 0x0B02);
+    i2c_writeReg16(0x57, 0x1C00);
+    i2c_writeReg16(0x58, 0x9CDD);
+    i2c_writeReg16(0x5A, 0x06DB);
+    i2c_writeReg16(0x63, 0x16AD);
+    i2c_writeReg16(0x67, 0x0628);
+    i2c_writeReg16(0x68, 0x05E5);
+    i2c_writeReg16(0x69, 0x0555);
+    i2c_writeReg16(0x6A, 0x04B8);
+    i2c_writeReg16(0x6B, 0x02FE);
+    i2c_writeReg16(0x6C, 0x01DD);
+    i2c_writeReg16(0x6D, 0x00B1);
+    i2c_writeReg16(0x6E, 0x0F82);
+    i2c_writeReg16(0x6F, 0x017A);
+    i2c_writeReg16(0x70, 0x004C);
+    i2c_writeReg16(0x71, 0x0F1D);
+    i2c_writeReg16(0x72, 0x0D91);
+    i2c_writeReg16(0x73, 0x0A3E);
+    i2c_writeReg16(0x74, 0x090F);
+    i2c_writeReg16(0x75, 0x0833);
+    i2c_writeReg16(0x76, 0x0806);
+
+    i2c_writeReg16(0x30, 0x40A4);
+    delayMs(100);
+
+    i2c_writeReg16(0x30, 0x40A6);   /* Start calibration       */
+    delayMs(100);
+    i2c_writeReg16(0x30, 0x4006);   /* Stop calibration        */
+    delayMs(100);
+
+    i2c_writeReg16(0x40, 0x0031);
+}
+
+void AT1846S_terminate()
+{
+    AT1846S_disableCtcss();
+    AT1846S_setFuncMode(AT1846S_OFF);
+}
+
+void AT1846S_setFrequency(const freq_t freq)
+{
+    /* The value to be written in registers is given by: 0.0016*freqency */
+    uint32_t val = (freq/1000)*16;
+    uint16_t fHi = (val >> 16) & 0xFFFF;
+    uint16_t fLo = val & 0xFFFF;
+
+    i2c_writeReg16(0x05, 0x8763);
+    i2c_writeReg16(0x29, fHi);
+    i2c_writeReg16(0x2A, fLo);
+
+    _reloadConfig();
+}
+
+void AT1846S_setBandwidth(const AT1846S_bw_t band)
+{
+    if(band == AT1846S_BW_25)
+    {
+        /* 25kHz bandwidth */
+        i2c_writeReg16(0x15, 0x1F00);
+        i2c_writeReg16(0x32, 0x7564);
+        i2c_writeReg16(0x3A, 0x04C3);
+        i2c_writeReg16(0x3C, 0x1B34);
+        i2c_writeReg16(0x3F, 0x29D1);
+        i2c_writeReg16(0x48, 0x1F3C);
+        i2c_writeReg16(0x60, 0x0F17);
+        i2c_writeReg16(0x62, 0x3263);
+        i2c_writeReg16(0x65, 0x248A);
+        i2c_writeReg16(0x66, 0xFFAE);
+        i2c_writeReg16(0x7F, 0x0001);
+        i2c_writeReg16(0x06, 0x0024);
+        i2c_writeReg16(0x07, 0x0214);
+        i2c_writeReg16(0x08, 0x0224);
+        i2c_writeReg16(0x09, 0x0314);
+        i2c_writeReg16(0x0A, 0x0324);
+        i2c_writeReg16(0x0B, 0x0344);
+        i2c_writeReg16(0x0C, 0x0384);
+        i2c_writeReg16(0x0D, 0x1384);
+        i2c_writeReg16(0x0E, 0x1B84);
+        i2c_writeReg16(0x0F, 0x3F84);
+        i2c_writeReg16(0x12, 0xE0EB);
+        i2c_writeReg16(0x7F, 0x0000);
+        _maskSetRegister(0x30, 0x3000, 0x3000);
+    }
+    else
+    {
+        /* 12.5kHz bandwidth */
+        i2c_writeReg16(0x15, 0x1100);
+        i2c_writeReg16(0x32, 0x4495);
+        i2c_writeReg16(0x3A, 0x00C3);
+        i2c_writeReg16(0x3F, 0x29D1);
+        i2c_writeReg16(0x3C, 0x1B34);
+        i2c_writeReg16(0x48, 0x19B1);
+        i2c_writeReg16(0x60, 0x0F17);
+        i2c_writeReg16(0x62, 0x1425);
+        i2c_writeReg16(0x65, 0x2494);
+        i2c_writeReg16(0x66, 0xEB2E);
+        i2c_writeReg16(0x7F, 0x0001);
+        i2c_writeReg16(0x06, 0x0014);
+        i2c_writeReg16(0x07, 0x020C);
+        i2c_writeReg16(0x08, 0x0214);
+        i2c_writeReg16(0x09, 0x030C);
+        i2c_writeReg16(0x0A, 0x0314);
+        i2c_writeReg16(0x0B, 0x0324);
+        i2c_writeReg16(0x0C, 0x0344);
+        i2c_writeReg16(0x0D, 0x1344);
+        i2c_writeReg16(0x0E, 0x1B44);
+        i2c_writeReg16(0x0F, 0x3F44);
+        i2c_writeReg16(0x12, 0xE0EB);
+        i2c_writeReg16(0x7F, 0x0000);
+        _maskSetRegister(0x30, 0x3000, 0x0000);
+    }
+
+    _reloadConfig();
+}
+
+void AT1846S_setOpMode(const AT1846S_op_t mode)
+{
+    if(mode == AT1846S_OP_DMR)
+    {
+        /* DMR mode */
+
+    }
+    else
+    {
+        /* FM mode */
+        i2c_writeReg16(0x58, 0x9C1D);
+        i2c_writeReg16(0x40, 0x0030);
+    }
+
+    _reloadConfig();
+}
+
+void AT1846S_setFuncMode(const AT1846S_func_t mode)
+{
+    /*
+     * Functional mode is controlled by bits 5 (RX on) and 6 (TX on) in register
+     * 0x30. With a cast and shift we can do it easily...
+     *
+     * Note about sanity check: if value is greater than 0x0040 we are trying to
+     * turn on both RX and TX, which is NOT good.
+     */
+
+    uint16_t value = ((uint16_t) mode) << 5;
+    if(value > 0x0040) return;
+    _maskSetRegister(0x30, 0x0060, value);
+}
+
+void AT1846S_enableTxCtcss(tone_t freq)
+{
+    i2c_writeReg16(0x4A, freq*10);
+    i2c_writeReg16(0x4B, 0x0000);
+    i2c_writeReg16(0x4C, 0x0000);
+    _maskSetRegister(0x4E, 0x0600, 0x0600);
+}
+
+void AT1846S_disableCtcss()
+{
+    i2c_writeReg16(0x4A, 0x0000);
+    _maskSetRegister(0x4E, 0x0600, 0x0000); /* Disable TX CTCSS */
+}
+
+uint16_t AT1846S_readRSSI()
+{
+    return i2c_readReg16(0x1B);
+}
+
+void AT1846S_setPgaGain(const uint8_t gain)
+{
+    uint16_t pga = (gain & 0x1F) << 6;
+    _maskSetRegister(0x0A, 0x07C0, pga);
+}
+
+void AT1846S_setMicGain(const uint8_t gain)
+{
+    _maskSetRegister(0x41, 0x007F, ((uint16_t) gain));
+}
+
+void AT1846S_setAgcGain(const uint8_t gain)
+{
+    uint16_t agc = (gain & 0x0F) << 8;
+    _maskSetRegister(0x44, 0x0F00, agc);
+}
+
+void AT1846S_setTxDeviation(const uint16_t dev)
+{
+    uint16_t value = (dev & 0x03FF) << 6;
+    _maskSetRegister(0x59, 0xFFC0, value);
+}
+
+void AT1846S_setRxAudioGain(const uint8_t gainWb, const uint8_t gainNb)
+{
+    uint16_t value = (gainWb & 0x0F) << 8;
+    _maskSetRegister(0x44, 0x0F00, value);
+    _maskSetRegister(0x44, 0x000F, ((uint16_t) gainNb));
+}
+
+void AT1846S_setNoise1Thresholds(const uint8_t highTsh, const uint8_t lowTsh)
+{
+    uint16_t value = ((highTsh & 0x1f) << 8) | (lowTsh & 0x1F);
+    i2c_writeReg16(0x48, value);
+}
+
+void AT1846S_setNoise2Thresholds(const uint8_t highTsh, const uint8_t lowTsh)
+{
+    uint16_t value = ((highTsh & 0x1f) << 8) | (lowTsh & 0x1F);
+    i2c_writeReg16(0x60, value);
+}
+
+void AT1846S_setRssiThresholds(const uint8_t highTsh, const uint8_t lowTsh)
+{
+    uint16_t value = ((highTsh & 0x1f) << 8) | (lowTsh & 0x1F);
+    i2c_writeReg16(0x3F, value);
+}
+
+void AT1846S_setPaDrive(const uint8_t value)
+{
+    uint16_t pa = value << 11;
+    _maskSetRegister(0x0A, 0x7800, pa);
+}
+
+void AT1846S_setAnalogSqlThresh(const uint8_t thresh)
+{
+    i2c_writeReg16(0x49, ((uint16_t) thresh));
+}
diff --git a/platform/drivers/baseband/interfaces_UV3x0.c b/platform/drivers/baseband/interfaces_UV3x0.c
index 4ed865cb..09e62b36 100644
--- a/platform/drivers/baseband/interfaces_UV3x0.c
+++ b/platform/drivers/baseband/interfaces_UV3x0.c
@@ -69,17 +69,14 @@ void i2c_writeReg16(uint8_t reg, uint16_t value)
 
 uint16_t i2c_readReg16(uint8_t reg)
 {
-    uint8_t valHi = 0;
-    uint8_t valLo = 0;
-
     _i2c_start();
     _i2c_write(devAddr);
     _i2c_write(reg);
     _i2c_start();
     _i2c_write(devAddr | 0x01);
-    _i2c_read(valHi);
+    uint8_t valHi = _i2c_read();
     _i2c_ack();
-    _i2c_read(valLo);
+    uint8_t valLo = _i2c_read();
     _i2c_nack();
     _i2c_stop();
 
@@ -92,10 +89,39 @@ uint16_t i2c_readReg16(uint8_t reg)
 
 void uSpi_init()
 {
+    gpio_setMode(DMR_CS,    OUTPUT);
+    gpio_setMode(DMR_CLK,   OUTPUT);
+    gpio_setMode(DMR_MOSI,  OUTPUT);
+    gpio_setMode(DMR_MISO,  OUTPUT);
 }
 
 uint8_t uSpi_sendRecv(uint8_t val)
 {
+    gpio_clearPin(DMR_CLK);
+
+    uint8_t incoming = 0;
+    uint8_t cnt = 0;
+
+    for(; cnt < 8; cnt++)
+    {
+        gpio_setPin(DMR_CLK);
+
+        if(val & (0x80 >> cnt))
+        {
+            gpio_setPin(DMR_MOSI);
+        }
+        else
+        {
+            gpio_clearPin(DMR_MOSI);
+        }
+
+        delayUs(1);
+        gpio_clearPin(DMR_CLK);
+        incoming = (incoming << 1) | gpio_readPin(DMR_MISO);
+        delayUs(1);
+    }
+
+    return incoming;
 }
 
 /*
@@ -197,7 +223,7 @@ void _i2c_write(uint8_t val)
     }
 
     /* Clock cycle for slave ACK/NACK */
-    gpio_setMode(I2C_SDA, INPUT_PULL_UP);
+    gpio_setMode(I2C_SDA, INPUT);
     gpio_clearPin(I2C_SCL);
     delayUs(2);
     gpio_setPin(I2C_SCL);
diff --git a/platform/targets/MD-UV380/hwconfig.h b/platform/targets/MD-UV380/hwconfig.h
index efa25585..7f55ece1 100644
--- a/platform/targets/MD-UV380/hwconfig.h
+++ b/platform/targets/MD-UV380/hwconfig.h
@@ -106,8 +106,8 @@
 #define FLASH_SDI GPIOB,5
 
 /* Audio control */
-#define AMP_EN   GPIOB,9
-#define SPK_MUTE GPIOB,8
+#define AUDIO_AMP_EN GPIOB,9
+#define SPK_MUTE     GPIOB,8
 
 /* GPS, for the devices who have it */
 #define GPS_EN   GPIOA,9