mirror of
https://github.com/OneOfEleven/uv-k5-firmware-custom.git
synced 2025-06-18 22:29:50 +03:00
Initial commit
This commit is contained in:
165
driver/adc.c
Normal file
165
driver/adc.c
Normal file
@ -0,0 +1,165 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ARMCM0.h"
|
||||
#include "adc.h"
|
||||
#include "bsp/dp32g030/irq.h"
|
||||
#include "bsp/dp32g030/saradc.h"
|
||||
#include "bsp/dp32g030/syscon.h"
|
||||
|
||||
uint8_t ADC_GetChannelNumber(ADC_CH_MASK Mask)
|
||||
{
|
||||
if (Mask & ADC_CH15) return 15U;
|
||||
if (Mask & ADC_CH14) return 14U;
|
||||
if (Mask & ADC_CH13) return 13U;
|
||||
if (Mask & ADC_CH12) return 12U;
|
||||
if (Mask & ADC_CH11) return 11U;
|
||||
if (Mask & ADC_CH10) return 10U;
|
||||
if (Mask & ADC_CH9) return 9U;
|
||||
if (Mask & ADC_CH8) return 8U;
|
||||
if (Mask & ADC_CH7) return 7U;
|
||||
if (Mask & ADC_CH6) return 6U;
|
||||
if (Mask & ADC_CH5) return 5U;
|
||||
if (Mask & ADC_CH4) return 4U;
|
||||
if (Mask & ADC_CH3) return 3U;
|
||||
if (Mask & ADC_CH2) return 2U;
|
||||
if (Mask & ADC_CH1) return 1U;
|
||||
if (Mask & ADC_CH0) return 0U;
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
void ADC_Disable(void)
|
||||
{
|
||||
SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_DISABLE;
|
||||
}
|
||||
|
||||
void ADC_Enable(void)
|
||||
{
|
||||
SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_ENABLE;
|
||||
}
|
||||
|
||||
void ADC_SoftReset(void)
|
||||
{
|
||||
SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_ASSERT;
|
||||
SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_DEASSERT;
|
||||
}
|
||||
|
||||
// The firmware thinks W_SARADC_SMPL_CLK_SEL is at [8:7] but the TRM says it's at [10:9]
|
||||
#define FW_R_SARADC_SMPL_SHIFT 7
|
||||
#define FW_R_SARADC_SMPL_MASK (3U << FW_R_SARADC_SMPL_SHIFT)
|
||||
|
||||
uint32_t ADC_GetClockConfig(void)
|
||||
{
|
||||
uint32_t Value;
|
||||
|
||||
Value = SYSCON_CLK_SEL;
|
||||
|
||||
Value = 0
|
||||
| (Value & ~(SYSCON_CLK_SEL_R_PLL_MASK | FW_R_SARADC_SMPL_MASK))
|
||||
| (((Value & SYSCON_CLK_SEL_R_PLL_MASK) >> SYSCON_CLK_SEL_R_PLL_SHIFT) << SYSCON_CLK_SEL_W_PLL_SHIFT)
|
||||
| (((Value & FW_R_SARADC_SMPL_MASK) >> FW_R_SARADC_SMPL_SHIFT) << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT)
|
||||
;
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
void ADC_Configure(ADC_Config_t *pAdc)
|
||||
{
|
||||
SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SARADC_MASK) | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE;
|
||||
|
||||
ADC_Disable();
|
||||
|
||||
SYSCON_CLK_SEL = (ADC_GetClockConfig() & ~SYSCON_CLK_SEL_W_SARADC_SMPL_MASK) | ((pAdc->CLK_SEL << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT) & SYSCON_CLK_SEL_W_SARADC_SMPL_MASK);
|
||||
|
||||
SARADC_CFG = 0
|
||||
| (SARADC_CFG & ~(0
|
||||
| SARADC_CFG_CH_SEL_MASK
|
||||
| SARADC_CFG_AVG_MASK
|
||||
| SARADC_CFG_CONT_MASK
|
||||
| SARADC_CFG_SMPL_SETUP_MASK
|
||||
| SARADC_CFG_MEM_MODE_MASK
|
||||
| SARADC_CFG_SMPL_CLK_MASK
|
||||
| SARADC_CFG_SMPL_WIN_MASK
|
||||
| SARADC_CFG_ADC_TRIG_MASK
|
||||
| SARADC_CFG_DMA_EN_MASK
|
||||
))
|
||||
| ((pAdc->CH_SEL << SARADC_CFG_CH_SEL_SHIFT) & SARADC_CFG_CH_SEL_MASK)
|
||||
| ((pAdc->AVG << SARADC_CFG_AVG_SHIFT) & SARADC_CFG_AVG_MASK)
|
||||
| ((pAdc->CONT << SARADC_CFG_CONT_SHIFT) & SARADC_CFG_CONT_MASK)
|
||||
| ((pAdc->SMPL_SETUP << SARADC_CFG_SMPL_SETUP_SHIFT) & SARADC_CFG_SMPL_SETUP_MASK)
|
||||
| ((pAdc->MEM_MODE << SARADC_CFG_MEM_MODE_SHIFT) & SARADC_CFG_MEM_MODE_MASK)
|
||||
| ((pAdc->SMPL_CLK << SARADC_CFG_SMPL_CLK_SHIFT) & SARADC_CFG_SMPL_CLK_MASK)
|
||||
| ((pAdc->SMPL_WIN << SARADC_CFG_SMPL_WIN_SHIFT) & SARADC_CFG_SMPL_WIN_MASK)
|
||||
| ((pAdc->ADC_TRIG << SARADC_CFG_ADC_TRIG_SHIFT) & SARADC_CFG_ADC_TRIG_MASK)
|
||||
| ((pAdc->DMA_EN << SARADC_CFG_DMA_EN_SHIFT) & SARADC_CFG_DMA_EN_MASK)
|
||||
;
|
||||
|
||||
SARADC_EXTTRIG_SEL = pAdc->EXTTRIG_SEL;
|
||||
|
||||
if (pAdc->CALIB_OFFSET_VALID) {
|
||||
SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_YES;
|
||||
} else {
|
||||
SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_NO;
|
||||
}
|
||||
if (pAdc->CALIB_KD_VALID) {
|
||||
SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_YES;
|
||||
} else {
|
||||
SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_NO;
|
||||
}
|
||||
|
||||
SARADC_IF = 0xFFFFFFFF;
|
||||
SARADC_IE = 0
|
||||
| (SARADC_IE & ~(0
|
||||
| SARADC_IE_CHx_EOC_MASK
|
||||
| SARADC_IE_FIFO_FULL_MASK
|
||||
| SARADC_IE_FIFO_HFULL_MASK
|
||||
))
|
||||
| ((pAdc->IE_CHx_EOC << SARADC_IE_CHx_EOC_SHIFT) & SARADC_IE_CHx_EOC_MASK)
|
||||
| ((pAdc->IE_FIFO_FULL << SARADC_IE_FIFO_FULL_SHIFT) & SARADC_IE_FIFO_FULL_MASK)
|
||||
| ((pAdc->IE_FIFO_HFULL << SARADC_IE_FIFO_HFULL_SHIFT) & SARADC_IE_FIFO_HFULL_MASK)
|
||||
;
|
||||
|
||||
if (SARADC_IE == 0) {
|
||||
NVIC_DisableIRQ(DP32_SARADC_IRQn);
|
||||
} else {
|
||||
NVIC_EnableIRQ(DP32_SARADC_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
void ADC_Start(void)
|
||||
{
|
||||
SARADC_START = (SARADC_START & ~SARADC_START_START_MASK) | SARADC_START_START_BITS_ENABLE;
|
||||
}
|
||||
|
||||
bool ADC_CheckEndOfConversion(ADC_CH_MASK Mask)
|
||||
{
|
||||
volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0;
|
||||
uint8_t Channel = ADC_GetChannelNumber(Mask);
|
||||
|
||||
return (pChannels[Channel].STAT & ADC_CHx_STAT_EOC_MASK) >> ADC_CHx_STAT_EOC_SHIFT;
|
||||
}
|
||||
|
||||
uint16_t ADC_GetValue(ADC_CH_MASK Mask)
|
||||
{
|
||||
volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0;
|
||||
uint8_t Channel = ADC_GetChannelNumber(Mask);
|
||||
|
||||
SARADC_IF = 1 << Channel; // TODO: Or just use 'Mask'
|
||||
|
||||
return (pChannels[Channel].DATA & ADC_CHx_DATA_DATA_MASK) >> ADC_CHx_DATA_DATA_SHIFT;
|
||||
}
|
||||
|
74
driver/adc.h
Normal file
74
driver/adc.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_ADC_H
|
||||
#define DRIVER_ADC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum ADC_CH_MASK {
|
||||
ADC_CH0 = 0x0001U,
|
||||
ADC_CH1 = 0x0002U,
|
||||
ADC_CH2 = 0x0004U,
|
||||
ADC_CH3 = 0x0008U,
|
||||
ADC_CH4 = 0x0010U,
|
||||
ADC_CH5 = 0x0020U,
|
||||
ADC_CH6 = 0x0040U,
|
||||
ADC_CH7 = 0x0080U,
|
||||
ADC_CH8 = 0x0100U,
|
||||
ADC_CH9 = 0x0200U,
|
||||
ADC_CH10 = 0x0400U,
|
||||
ADC_CH11 = 0x0800U,
|
||||
ADC_CH12 = 0x1000U,
|
||||
ADC_CH13 = 0x2000U,
|
||||
ADC_CH14 = 0x4000U,
|
||||
ADC_CH15 = 0x8000U,
|
||||
};
|
||||
|
||||
typedef enum ADC_CH_MASK ADC_CH_MASK;
|
||||
|
||||
typedef struct {
|
||||
uint8_t CLK_SEL;
|
||||
ADC_CH_MASK CH_SEL;
|
||||
uint8_t AVG;
|
||||
uint8_t CONT;
|
||||
uint8_t MEM_MODE;
|
||||
uint8_t SMPL_CLK;
|
||||
uint8_t SMPL_SETUP;
|
||||
uint8_t SMPL_WIN;
|
||||
uint8_t ADC_TRIG;
|
||||
uint16_t EXTTRIG_SEL;
|
||||
bool CALIB_OFFSET_VALID;
|
||||
bool CALIB_KD_VALID;
|
||||
uint8_t DMA_EN;
|
||||
uint16_t IE_CHx_EOC;
|
||||
uint8_t IE_FIFO_HFULL;
|
||||
uint8_t IE_FIFO_FULL;
|
||||
} ADC_Config_t;
|
||||
|
||||
uint8_t ADC_GetChannelNumber(ADC_CH_MASK Mask);
|
||||
void ADC_Disable(void);
|
||||
void ADC_Enable(void);
|
||||
void ADC_SoftReset(void);
|
||||
uint32_t ADC_GetClockConfig(void);
|
||||
void ADC_Configure(ADC_Config_t *pAdc);
|
||||
void ADC_Start(void);
|
||||
bool ADC_CheckEndOfConversion(ADC_CH_MASK Mask);
|
||||
uint16_t ADC_GetValue(ADC_CH_MASK Mask);
|
||||
|
||||
#endif
|
||||
|
72
driver/aes.c
Normal file
72
driver/aes.c
Normal file
@ -0,0 +1,72 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bsp/dp32g030/aes.h"
|
||||
#include "driver/aes.h"
|
||||
|
||||
static void AES_Setup_ENC_CBC(bool IsDecrypt, const void *pKey, const void *pIv)
|
||||
{
|
||||
const uint32_t *pK = (const uint32_t *)pKey;
|
||||
const uint32_t *pI = (const uint32_t *)pIv;
|
||||
|
||||
AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_DISABLE;
|
||||
AES_CR = AES_CR_CHMOD_BITS_CBC;
|
||||
AES_KEYR3 = pK[0];
|
||||
AES_KEYR2 = pK[1];
|
||||
AES_KEYR1 = pK[2];
|
||||
AES_KEYR0 = pK[3];
|
||||
AES_IVR3 = pI[0];
|
||||
AES_IVR2 = pI[1];
|
||||
AES_IVR1 = pI[2];
|
||||
AES_IVR0 = pI[3];
|
||||
AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_ENABLE;
|
||||
}
|
||||
|
||||
static void AES_Transform(const void *pIn, void *pOut)
|
||||
{
|
||||
const uint32_t *pI = (const uint32_t *)pIn;
|
||||
uint32_t *pO = (uint32_t *)pOut;
|
||||
|
||||
AES_DINR = pI[0];
|
||||
AES_DINR = pI[1];
|
||||
AES_DINR = pI[2];
|
||||
AES_DINR = pI[3];
|
||||
|
||||
while ((AES_SR & AES_SR_CCF_MASK) == AES_SR_CCF_BITS_NOT_COMPLETE) {
|
||||
}
|
||||
|
||||
pO[0] = AES_DOUTR;
|
||||
pO[1] = AES_DOUTR;
|
||||
pO[2] = AES_DOUTR;
|
||||
pO[3] = AES_DOUTR;
|
||||
|
||||
AES_CR |= AES_CR_CCFC_BITS_SET;
|
||||
}
|
||||
|
||||
void AES_Encrypt(const void *pKey, const void *pIv, const void *pIn, void *pOut, uint8_t NumBlocks)
|
||||
{
|
||||
const uint8_t *pI = (const uint8_t *)pIn;
|
||||
uint8_t *pO = (uint8_t *)pOut;
|
||||
uint8_t i;
|
||||
|
||||
AES_Setup_ENC_CBC(0, pKey, pIv);
|
||||
for (i = 0; i < NumBlocks; i++) {
|
||||
AES_Transform(pI + (i * 16), pO + (i * 16));
|
||||
}
|
||||
}
|
||||
|
25
driver/aes.h
Normal file
25
driver/aes.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_AES_H
|
||||
#define DRIVER_AES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void AES_Encrypt(const void *pKey, const void *pIv, const void *pIn, void *pOut, uint8_t NumBlocks);
|
||||
|
||||
#endif
|
||||
|
37
driver/backlight.c
Normal file
37
driver/backlight.c
Normal file
@ -0,0 +1,37 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "backlight.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "settings.h"
|
||||
|
||||
uint8_t gBacklightCountdown;
|
||||
|
||||
void BACKLIGHT_TurnOn(void)
|
||||
{
|
||||
if (gEeprom.BACKLIGHT)
|
||||
{
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT);
|
||||
#if 0
|
||||
gBacklightCountdown = 1 + (gEeprom.BACKLIGHT * 2);
|
||||
#else
|
||||
// much longer backlight times
|
||||
gBacklightCountdown = (gEeprom.BACKLIGHT * 20) - 19;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
27
driver/backlight.h
Normal file
27
driver/backlight.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_BACKLIGHT_H
|
||||
#define DRIVER_BACKLIGHT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint8_t gBacklightCountdown;
|
||||
|
||||
void BACKLIGHT_TurnOn(void);
|
||||
|
||||
#endif
|
||||
|
57
driver/bk1080-regs.h
Normal file
57
driver/bk1080-regs.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BK1080_REGS_H
|
||||
#define BK1080_REGS_H
|
||||
|
||||
enum BK1080_Register_t {
|
||||
BK1080_REG_00 = 0x00U,
|
||||
BK1080_REG_02_POWER_CONFIGURATION = 0x02U,
|
||||
BK1080_REG_03_CHANNEL = 0x03U,
|
||||
BK1080_REG_05_SYSTEM_CONFIGURATION2 = 0x05U,
|
||||
BK1080_REG_07 = 0x07U,
|
||||
BK1080_REG_10 = 0x0AU,
|
||||
BK1080_REG_25_INTERNAL = 0x19U,
|
||||
};
|
||||
|
||||
typedef enum BK1080_Register_t BK1080_Register_t;
|
||||
|
||||
// REG 07
|
||||
|
||||
#define BK1080_REG_07_SHIFT_FREQD 4
|
||||
#define BK1080_REG_07_SHIFT_SNR 0
|
||||
|
||||
#define BK1080_REG_07_MASK_FREQD (0xFFFU << BK1080_REG_07_SHIFT_FREQD)
|
||||
#define BK1080_REG_07_MASK_SNR (0x00FU << BK1080_REG_07_SHIFT_SNR)
|
||||
|
||||
#define BK1080_REG_07_GET_FREQD(x) (((x) & BK1080_REG_07_MASK_FREQD) >> BK1080_REG_07_SHIFT_FREQD)
|
||||
#define BK1080_REG_07_GET_SNR(x) (((x) & BK1080_REG_07_MASK_SNR) >> BK1080_REG_07_SHIFT_SNR)
|
||||
|
||||
// REG 10
|
||||
|
||||
#define BK1080_REG_10_SHIFT_AFCRL 12
|
||||
#define BK1080_REG_10_SHIFT_RSSI 0
|
||||
|
||||
#define BK1080_REG_10_MASK_AFCRL (0x01U << BK1080_REG_10_SHIFT_AFCRL)
|
||||
#define BK1080_REG_10_MASK_RSSI (0xFFU << BK1080_REG_10_SHIFT_RSSI)
|
||||
|
||||
#define BK1080_REG_10_AFCRL_NOT_RAILED (0U << BK1080_REG_10_SHIFT_AFCRL)
|
||||
#define BK1080_REG_10_AFCRL_RAILED (1U << BK1080_REG_10_SHIFT_AFCRL)
|
||||
|
||||
#define BK1080_REG_10_GET_RSSI(x) (((x) & BK1080_REG_10_MASK_RSSI) >> BK1080_REG_10_SHIFT_RSSI)
|
||||
|
||||
#endif
|
||||
|
115
driver/bk1080.c
Normal file
115
driver/bk1080.c
Normal file
@ -0,0 +1,115 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bk1080.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/system.h"
|
||||
#include "misc.h"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
static const uint16_t BK1080_RegisterTable[] = {
|
||||
0x0008, 0x1080, 0x0201, 0x0000,
|
||||
0x40C0, 0x0A1F, 0x002E, 0x02FF,
|
||||
0x5B11, 0x0000, 0x411E, 0x0000,
|
||||
0xCE00, 0x0000, 0x0000, 0x1000,
|
||||
0x3197, 0x0000, 0x13FF, 0x9852,
|
||||
0x0000, 0x0000, 0x0008, 0x0000,
|
||||
0x51E1, 0xA8BC, 0x2645, 0x00E4,
|
||||
0x1CD8, 0x3A50, 0xEAE0, 0x3000,
|
||||
0x0200, 0x0000,
|
||||
};
|
||||
|
||||
static bool gIsInitBK1080;
|
||||
|
||||
uint16_t BK1080_BaseFrequency;
|
||||
uint16_t BK1080_FrequencyDeviation;
|
||||
|
||||
void BK1080_Init(uint16_t Frequency, bool bDoScan)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (bDoScan) {
|
||||
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BK1080);
|
||||
|
||||
if (!gIsInitBK1080) {
|
||||
for (i = 0; i < ARRAY_SIZE(BK1080_RegisterTable); i++) {
|
||||
BK1080_WriteRegister(i, BK1080_RegisterTable[i]);
|
||||
}
|
||||
SYSTEM_DelayMs(250);
|
||||
BK1080_WriteRegister(BK1080_REG_25_INTERNAL, 0xA83C);
|
||||
BK1080_WriteRegister(BK1080_REG_25_INTERNAL, 0xA8BC);
|
||||
SYSTEM_DelayMs(60);
|
||||
gIsInitBK1080 = true;
|
||||
} else {
|
||||
BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0201);
|
||||
}
|
||||
BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, 0x0A5F);
|
||||
BK1080_WriteRegister(BK1080_REG_03_CHANNEL, Frequency - 760);
|
||||
SYSTEM_DelayMs(10);
|
||||
BK1080_WriteRegister(BK1080_REG_03_CHANNEL, (Frequency - 760) | 0x8000);
|
||||
} else {
|
||||
BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0241);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BK1080);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t BK1080_ReadRegister(BK1080_Register_t Register)
|
||||
{
|
||||
uint8_t Value[2];
|
||||
|
||||
I2C_Start();
|
||||
I2C_Write(0x80);
|
||||
I2C_Write((Register << 1) | I2C_READ);
|
||||
I2C_ReadBuffer(Value, sizeof(Value));
|
||||
I2C_Stop();
|
||||
return (Value[0] << 8) | Value[1];
|
||||
}
|
||||
|
||||
void BK1080_WriteRegister(BK1080_Register_t Register, uint16_t Value)
|
||||
{
|
||||
I2C_Start();
|
||||
I2C_Write(0x80);
|
||||
I2C_Write((Register << 1) | I2C_WRITE);
|
||||
Value = ((Value >> 8) & 0xFF) | ((Value & 0xFF) << 8);
|
||||
I2C_WriteBuffer(&Value, sizeof(Value));
|
||||
I2C_Stop();
|
||||
}
|
||||
|
||||
void BK1080_Mute(bool Mute)
|
||||
{
|
||||
if (Mute) {
|
||||
BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x4201);
|
||||
} else {
|
||||
BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0201);
|
||||
}
|
||||
}
|
||||
|
||||
void BK1080_SetFrequency(uint16_t Frequency)
|
||||
{
|
||||
BK1080_WriteRegister(BK1080_REG_03_CHANNEL, Frequency - 760);
|
||||
SYSTEM_DelayMs(10);
|
||||
BK1080_WriteRegister(BK1080_REG_03_CHANNEL, (Frequency - 760) | 0x8000);
|
||||
}
|
||||
|
||||
void BK1080_GetFrequencyDeviation(uint16_t Frequency)
|
||||
{
|
||||
BK1080_BaseFrequency = Frequency;
|
||||
BK1080_FrequencyDeviation = BK1080_ReadRegister(BK1080_REG_07) / 16;
|
||||
}
|
||||
|
35
driver/bk1080.h
Normal file
35
driver/bk1080.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_BK1080_H
|
||||
#define DRIVER_BK1080_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "driver/bk1080-regs.h"
|
||||
|
||||
extern uint16_t BK1080_BaseFrequency;
|
||||
extern uint16_t BK1080_FrequencyDeviation;
|
||||
|
||||
void BK1080_Init(uint16_t Frequency, bool bDoScan);
|
||||
uint16_t BK1080_ReadRegister(BK1080_Register_t Register);
|
||||
void BK1080_WriteRegister(BK1080_Register_t Register, uint16_t Value);
|
||||
void BK1080_Mute(bool Mute);
|
||||
void BK1080_SetFrequency(uint16_t Frequency);
|
||||
void BK1080_GetFrequencyDeviation(uint16_t Frequency);
|
||||
|
||||
#endif
|
||||
|
353
driver/bk4819-regs.h
Normal file
353
driver/bk4819-regs.h
Normal file
@ -0,0 +1,353 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BK4819_REGS_H
|
||||
#define BK4819_REGS_H
|
||||
|
||||
enum BK4819_REGISTER_t {
|
||||
BK4819_REG_00 = 0x00U,
|
||||
BK4819_REG_02 = 0x02U,
|
||||
BK4819_REG_06 = 0x06U,
|
||||
BK4819_REG_07 = 0x07U,
|
||||
BK4819_REG_08 = 0x08U,
|
||||
BK4819_REG_09 = 0x09U,
|
||||
BK4819_REG_0B = 0x0BU,
|
||||
BK4819_REG_0C = 0x0CU,
|
||||
BK4819_REG_0D = 0x0DU,
|
||||
BK4819_REG_0E = 0x0EU,
|
||||
BK4819_REG_10 = 0x10U,
|
||||
BK4819_REG_11 = 0x11U,
|
||||
BK4819_REG_12 = 0x12U,
|
||||
BK4819_REG_13 = 0x13U,
|
||||
BK4819_REG_14 = 0x14U,
|
||||
BK4819_REG_19 = 0x19U,
|
||||
BK4819_REG_1F = 0x1FU,
|
||||
BK4819_REG_20 = 0x20U,
|
||||
BK4819_REG_21 = 0x21U,
|
||||
BK4819_REG_24 = 0x24U,
|
||||
BK4819_REG_28 = 0x28U,
|
||||
BK4819_REG_29 = 0x29U,
|
||||
BK4819_REG_2B = 0x2BU,
|
||||
BK4819_REG_30 = 0x30U,
|
||||
BK4819_REG_31 = 0x31U,
|
||||
BK4819_REG_32 = 0x32U,
|
||||
BK4819_REG_33 = 0x33U,
|
||||
BK4819_REG_36 = 0x36U,
|
||||
BK4819_REG_37 = 0x37U,
|
||||
BK4819_REG_38 = 0x38U,
|
||||
BK4819_REG_39 = 0x39U,
|
||||
BK4819_REG_3A = 0x3AU,
|
||||
BK4819_REG_3B = 0x3BU,
|
||||
BK4819_REG_3C = 0x3CU,
|
||||
BK4819_REG_3E = 0x3EU,
|
||||
BK4819_REG_3F = 0x3FU,
|
||||
BK4819_REG_43 = 0x43U,
|
||||
BK4819_REG_46 = 0x46U,
|
||||
BK4819_REG_47 = 0x47U,
|
||||
BK4819_REG_48 = 0x48U,
|
||||
BK4819_REG_49 = 0x49U,
|
||||
BK4819_REG_4D = 0x4DU,
|
||||
BK4819_REG_4E = 0x4EU,
|
||||
BK4819_REG_4F = 0x4FU,
|
||||
BK4819_REG_50 = 0x50U,
|
||||
BK4819_REG_51 = 0x51U,
|
||||
BK4819_REG_52 = 0x52U,
|
||||
BK4819_REG_58 = 0x58U,
|
||||
BK4819_REG_59 = 0x59U,
|
||||
BK4819_REG_5A = 0x5AU,
|
||||
BK4819_REG_5B = 0x5BU,
|
||||
BK4819_REG_5C = 0x5CU,
|
||||
BK4819_REG_5D = 0x5DU,
|
||||
BK4819_REG_5F = 0x5FU,
|
||||
BK4819_REG_63 = 0x63U,
|
||||
BK4819_REG_64 = 0x64U,
|
||||
BK4819_REG_65 = 0x65U,
|
||||
BK4819_REG_67 = 0x67U,
|
||||
BK4819_REG_68 = 0x68U,
|
||||
BK4819_REG_69 = 0x69U,
|
||||
BK4819_REG_6A = 0x6AU,
|
||||
BK4819_REG_6F = 0x6FU,
|
||||
BK4819_REG_70 = 0x70U,
|
||||
BK4819_REG_71 = 0x71U,
|
||||
BK4819_REG_72 = 0x72U,
|
||||
BK4819_REG_78 = 0x78U,
|
||||
BK4819_REG_79 = 0x79U,
|
||||
BK4819_REG_7A = 0x7AU,
|
||||
BK4819_REG_7B = 0x7BU,
|
||||
BK4819_REG_7C = 0x7CU,
|
||||
BK4819_REG_7D = 0x7DU,
|
||||
BK4819_REG_7E = 0x7EU,
|
||||
};
|
||||
|
||||
typedef enum BK4819_REGISTER_t BK4819_REGISTER_t;
|
||||
|
||||
enum BK4819_GPIO_PIN_t {
|
||||
BK4819_GPIO6_PIN2 = 0,
|
||||
BK4819_GPIO5_PIN1 = 1,
|
||||
BK4819_GPIO4_PIN32 = 2,
|
||||
BK4819_GPIO3_PIN31 = 3,
|
||||
BK4819_GPIO2_PIN30 = 4,
|
||||
BK4819_GPIO1_PIN29_RED = 5,
|
||||
BK4819_GPIO0_PIN28_GREEN = 6,
|
||||
};
|
||||
|
||||
typedef enum BK4819_GPIO_PIN_t BK4819_GPIO_PIN_t;
|
||||
|
||||
// REG 02
|
||||
|
||||
#define BK4819_REG_02_SHIFT_FSK_TX_FINISHED 15
|
||||
#define BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY 14
|
||||
#define BK4819_REG_02_SHIFT_FSK_RX_FINISHED 13
|
||||
#define BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL 12
|
||||
#define BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND 11
|
||||
#define BK4819_REG_02_SHIFT_CxCSS_TAIL 10
|
||||
#define BK4819_REG_02_SHIFT_CDCSS_FOUND 9
|
||||
#define BK4819_REG_02_SHIFT_CDCSS_LOST 8
|
||||
#define BK4819_REG_02_SHIFT_CTCSS_FOUND 7
|
||||
#define BK4819_REG_02_SHIFT_CTCSS_LOST 6
|
||||
#define BK4819_REG_02_SHIFT_VOX_FOUND 5
|
||||
#define BK4819_REG_02_SHIFT_VOX_LOST 4
|
||||
#define BK4819_REG_02_SHIFT_SQUELCH_FOUND 3
|
||||
#define BK4819_REG_02_SHIFT_SQUELCH_LOST 2
|
||||
#define BK4819_REG_02_SHIFT_FSK_RX_SYNC 1
|
||||
|
||||
#define BK4819_REG_02_MASK_FSK_TX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_TX)
|
||||
#define BK4819_REG_02_MASK_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY)
|
||||
#define BK4819_REG_02_MASK_FSK_RX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_RX_FINISHED)
|
||||
#define BK4819_REG_02_MASK_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL)
|
||||
#define BK4819_REG_02_MASK_DTMF_5TONE_FOUND (1U << BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND)
|
||||
#define BK4819_REG_02_MASK_CxCSS_TAIL (1U << BK4819_REG_02_SHIFT_CxCSS_TAIL)
|
||||
#define BK4819_REG_02_MASK_CDCSS_FOUND (1U << BK4819_REG_02_SHIFT_CDCSS_FOUND)
|
||||
#define BK4819_REG_02_MASK_CDCSS_LOST (1U << BK4819_REG_02_SHIFT_CDCSS_LOST)
|
||||
#define BK4819_REG_02_MASK_CTCSS_FOUND (1U << BK4819_REG_02_SHIFT_CTCSS_FOUND)
|
||||
#define BK4819_REG_02_MASK_CTCSS_LOST (1U << BK4819_REG_02_SHIFT_CTCSS_LOST)
|
||||
#define BK4819_REG_02_MASK_VOX_FOUND (1U << BK4819_REG_02_SHIFT_VOX_FOUND)
|
||||
#define BK4819_REG_02_MASK_VOX_LOST (1U << BK4819_REG_02_SHIFT_VOX_LOST)
|
||||
#define BK4819_REG_02_MASK_SQUELCH_FOUND (1U << BK4819_REG_02_SHIFT_SQUELCH_FOUND)
|
||||
#define BK4819_REG_02_MASK_SQUELCH_LOST (1U << BK4819_REG_02_SHIFT_SQUELCH_LOST)
|
||||
#define BK4819_REG_02_MASK_FSK_RX_SYNC (1U << BK4819_REG_02_SHIFT_FSK_RX_SYNC)
|
||||
|
||||
#define BK4819_REG_02_FSK_TX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_TX_FINISHED)
|
||||
#define BK4819_REG_02_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY)
|
||||
#define BK4819_REG_02_FSK_RX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_RX_FINISHED)
|
||||
#define BK4819_REG_02_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL)
|
||||
#define BK4819_REG_02_DTMF_5TONE_FOUND (1U << BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND)
|
||||
#define BK4819_REG_02_CxCSS_TAIL (1U << BK4819_REG_02_SHIFT_CxCSS_TAIL)
|
||||
#define BK4819_REG_02_CDCSS_FOUND (1U << BK4819_REG_02_SHIFT_CDCSS_FOUND)
|
||||
#define BK4819_REG_02_CDCSS_LOST (1U << BK4819_REG_02_SHIFT_CDCSS_LOST)
|
||||
#define BK4819_REG_02_CTCSS_FOUND (1U << BK4819_REG_02_SHIFT_CTCSS_FOUND)
|
||||
#define BK4819_REG_02_CTCSS_LOST (1U << BK4819_REG_02_SHIFT_CTCSS_LOST)
|
||||
#define BK4819_REG_02_VOX_FOUND (1U << BK4819_REG_02_SHIFT_VOX_FOUND)
|
||||
#define BK4819_REG_02_VOX_LOST (1U << BK4819_REG_02_SHIFT_VOX_LOST)
|
||||
#define BK4819_REG_02_SQUELCH_FOUND (1U << BK4819_REG_02_SHIFT_SQUELCH_FOUND)
|
||||
#define BK4819_REG_02_SQUELCH_LOST (1U << BK4819_REG_02_SHIFT_SQUELCH_LOST)
|
||||
#define BK4819_REG_02_FSK_RX_SYNC (1U << BK4819_REG_02_SHIFT_FSK_RX_SYNC)
|
||||
|
||||
// REG 07
|
||||
|
||||
#define BK4819_REG_07_SHIFT_FREQUENCY_MODE 13
|
||||
#define BK4819_REG_07_SHIFT_FREQUENCY 0
|
||||
|
||||
#define BK4819_REG_07_MASK_FREQUENCY_MODE (0x0007U << BK4819_REG_07_SHIFT_FREQUENCY_MODE)
|
||||
#define BK4819_REG_07_MASK_FREQUENCY (0x1FFFU << BK4819_REG_07_SHIFT_FREQUENCY)
|
||||
|
||||
#define BK4819_REG_07_MODE_CTC1 (0U << BK4819_REG_07_SHIFT_FREQUENCY_MODE)
|
||||
#define BK4819_REG_07_MODE_CTC2 (1U << BK4819_REG_07_SHIFT_FREQUENCY_MODE)
|
||||
#define BK4819_REG_07_MODE_CDCSS (2U << BK4819_REG_07_SHIFT_FREQUENCY_MODE)
|
||||
|
||||
// REG 24
|
||||
|
||||
#define BK4819_REG_24_SHIFT_UNKNOWN_15 15
|
||||
#define BK4819_REG_24_SHIFT_THRESHOLD 7
|
||||
#define BK4819_REG_24_SHIFT_UNKNOWN_6 6
|
||||
#define BK4819_REG_24_SHIFT_ENABLE 5
|
||||
#define BK4819_REG_24_SHIFT_SELECT 4
|
||||
#define BK4819_REG_24_SHIFT_MAX_SYMBOLS 0
|
||||
|
||||
#define BK4819_REG_24_MASK_THRESHOLD (0x2FU << BK4819_REG_24_SHIFT_THRESHOLD)
|
||||
#define BK4819_REG_24_MASK_ENABLE (0x01U << BK4819_REG_24_SHIFT_ENABLE)
|
||||
#define BK4819_REG_24_MASK_SELECT (0x04U << BK4819_REG_24_SHIFT_SELECT)
|
||||
#define BK4819_REG_24_MASK_MAX_SYMBOLS (0x0FU << BK4819_REG_24_SHIFT_MAX_SYMBOLS)
|
||||
|
||||
#define BK4819_REG_24_ENABLE (0x01U << BK4819_REG_24_SHIFT_ENABLE)
|
||||
#define BK4819_REG_24_DISABLE (0x00U << BK4819_REG_24_SHIFT_ENABLE)
|
||||
#define BK4819_REG_24_SELECT_DTMF (0x01U << BK4819_REG_24_SHIFT_SELECT)
|
||||
#define BK4819_REG_24_SELECT_SELCALL (0x00U << BK4819_REG_24_SHIFT_SELECT)
|
||||
|
||||
// REG 30
|
||||
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB 15
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_UNKNOWN 14
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_RX_LINK 10
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_AF_DAC 9
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_DISC_MODE 8
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_PLL_VCO 4
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_PA_GAIN 3
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_MIC_ADC 2
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_TX_DSP 1
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_RX_DSP 0
|
||||
|
||||
#define BK4819_REG_30_MASK_ENABLE_VCO_CALIB (0x1U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB)
|
||||
#define BK4819_REG_30_MASK_ENABLE_UNKNOWN (0x1U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN)
|
||||
#define BK4819_REG_30_MASK_ENABLE_RX_LINK (0xFU << BK4819_REG_30_SHIFT_ENABLE_RX_LINK)
|
||||
#define BK4819_REG_30_MASK_ENABLE_AF_DAC (0x1U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC)
|
||||
#define BK4819_REG_30_MASK_ENABLE_DISC_MODE (0x1U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE)
|
||||
#define BK4819_REG_30_MASK_ENABLE_PLL_VCO (0xFU << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO)
|
||||
#define BK4819_REG_30_MASK_ENABLE_PA_GAIN (0x1U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN)
|
||||
#define BK4819_REG_30_MASK_ENABLE_MIC_ADC (0x1U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC)
|
||||
#define BK4819_REG_30_MASK_ENABLE_TX_DSP (0x1U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP)
|
||||
#define BK4819_REG_30_MASK_ENABLE_RX_DSP (0x1U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP)
|
||||
|
||||
enum {
|
||||
BK4819_REG_30_ENABLE_VCO_CALIB = (0x1U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB),
|
||||
BK4819_REG_30_DISABLE_VCO_CALIB = (0x0U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB),
|
||||
BK4819_REG_30_ENABLE_UNKNOWN = (0x1U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN),
|
||||
BK4819_REG_30_DISABLE_UNKNOWN = (0x0U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN),
|
||||
BK4819_REG_30_ENABLE_RX_LINK = (0xFU << BK4819_REG_30_SHIFT_ENABLE_RX_LINK),
|
||||
BK4819_REG_30_DISABLE_RX_LINK = (0x0U << BK4819_REG_30_SHIFT_ENABLE_RX_LINK),
|
||||
BK4819_REG_30_ENABLE_AF_DAC = (0x1U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC),
|
||||
BK4819_REG_30_DISABLE_AF_DAC = (0x0U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC),
|
||||
BK4819_REG_30_ENABLE_DISC_MODE = (0x1U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE),
|
||||
BK4819_REG_30_DISABLE_DISC_MODE = (0x0U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE),
|
||||
BK4819_REG_30_ENABLE_PLL_VCO = (0xFU << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO),
|
||||
BK4819_REG_30_DISABLE_PLL_VCO = (0x0U << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO),
|
||||
BK4819_REG_30_ENABLE_PA_GAIN = (0x1U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN),
|
||||
BK4819_REG_30_DISABLE_PA_GAIN = (0x0U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN),
|
||||
BK4819_REG_30_ENABLE_MIC_ADC = (0x1U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC),
|
||||
BK4819_REG_30_DISABLE_MIC_ADC = (0x0U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC),
|
||||
BK4819_REG_30_ENABLE_TX_DSP = (0x1U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP),
|
||||
BK4819_REG_30_DISABLE_TX_DSP = (0x0U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP),
|
||||
BK4819_REG_30_ENABLE_RX_DSP = (0x1U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP),
|
||||
BK4819_REG_30_DISABLE_RX_DSP = (0x0U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP),
|
||||
};
|
||||
|
||||
// REG 3F
|
||||
|
||||
#define BK4819_REG_3F_SHIFT_FSK_TX_FINISHED 15
|
||||
#define BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY 14
|
||||
#define BK4819_REG_3F_SHIFT_FSK_RX_FINISHED 13
|
||||
#define BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL 12
|
||||
#define BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND 11
|
||||
#define BK4819_REG_3F_SHIFT_CxCSS_TAIL 10
|
||||
#define BK4819_REG_3F_SHIFT_CDCSS_FOUND 9
|
||||
#define BK4819_REG_3F_SHIFT_CDCSS_LOST 8
|
||||
#define BK4819_REG_3F_SHIFT_CTCSS_FOUND 7
|
||||
#define BK4819_REG_3F_SHIFT_CTCSS_LOST 6
|
||||
#define BK4819_REG_3F_SHIFT_VOX_FOUND 5
|
||||
#define BK4819_REG_3F_SHIFT_VOX_LOST 4
|
||||
#define BK4819_REG_3F_SHIFT_SQUELCH_FOUND 3
|
||||
#define BK4819_REG_3F_SHIFT_SQUELCH_LOST 2
|
||||
#define BK4819_REG_3F_SHIFT_FSK_RX_SYNC 1
|
||||
|
||||
#define BK4819_REG_3F_MASK_FSK_TX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_TX)
|
||||
#define BK4819_REG_3F_MASK_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY)
|
||||
#define BK4819_REG_3F_MASK_FSK_RX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_RX_FINISHED)
|
||||
#define BK4819_REG_3F_MASK_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL)
|
||||
#define BK4819_REG_3F_MASK_DTMF_5TONE_FOUND (1U << BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND)
|
||||
#define BK4819_REG_3F_MASK_CxCSS_TAIL (1U << BK4819_REG_3F_SHIFT_CxCSS_TAIL)
|
||||
#define BK4819_REG_3F_MASK_CDCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CDCSS_FOUND)
|
||||
#define BK4819_REG_3F_MASK_CDCSS_LOST (1U << BK4819_REG_3F_SHIFT_CDCSS_LOST)
|
||||
#define BK4819_REG_3F_MASK_CTCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CTCSS_FOUND)
|
||||
#define BK4819_REG_3F_MASK_CTCSS_LOST (1U << BK4819_REG_3F_SHIFT_CTCSS_LOST)
|
||||
#define BK4819_REG_3F_MASK_VOX_FOUND (1U << BK4819_REG_3F_SHIFT_VOX_FOUND)
|
||||
#define BK4819_REG_3F_MASK_VOX_LOST (1U << BK4819_REG_3F_SHIFT_VOX_LOST)
|
||||
#define BK4819_REG_3F_MASK_SQUELCH_FOUND (1U << BK4819_REG_3F_SHIFT_SQUELCH_FOUND)
|
||||
#define BK4819_REG_3F_MASK_SQUELCH_LOST (1U << BK4819_REG_3F_SHIFT_SQUELCH_LOST)
|
||||
#define BK4819_REG_3F_MASK_FSK_RX_SYNC (1U << BK4819_REG_3F_SHIFT_FSK_RX_SYNC)
|
||||
|
||||
#define BK4819_REG_3F_FSK_TX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_TX_FINISHED)
|
||||
#define BK4819_REG_3F_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY)
|
||||
#define BK4819_REG_3F_FSK_RX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_RX_FINISHED)
|
||||
#define BK4819_REG_3F_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL)
|
||||
#define BK4819_REG_3F_DTMF_5TONE_FOUND (1U << BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND)
|
||||
#define BK4819_REG_3F_CxCSS_TAIL (1U << BK4819_REG_3F_SHIFT_CxCSS_TAIL)
|
||||
#define BK4819_REG_3F_CDCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CDCSS_FOUND)
|
||||
#define BK4819_REG_3F_CDCSS_LOST (1U << BK4819_REG_3F_SHIFT_CDCSS_LOST)
|
||||
#define BK4819_REG_3F_CTCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CTCSS_FOUND)
|
||||
#define BK4819_REG_3F_CTCSS_LOST (1U << BK4819_REG_3F_SHIFT_CTCSS_LOST)
|
||||
#define BK4819_REG_3F_VOX_FOUND (1U << BK4819_REG_3F_SHIFT_VOX_FOUND)
|
||||
#define BK4819_REG_3F_VOX_LOST (1U << BK4819_REG_3F_SHIFT_VOX_LOST)
|
||||
#define BK4819_REG_3F_SQUELCH_FOUND (1U << BK4819_REG_3F_SHIFT_SQUELCH_FOUND)
|
||||
#define BK4819_REG_3F_SQUELCH_LOST (1U << BK4819_REG_3F_SHIFT_SQUELCH_LOST)
|
||||
#define BK4819_REG_3F_FSK_RX_SYNC (1U << BK4819_REG_3F_SHIFT_FSK_RX_SYNC)
|
||||
|
||||
// REG 51
|
||||
|
||||
#define BK4819_REG_51_SHIFT_ENABLE_CxCSS 15
|
||||
#define BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT 14
|
||||
#define BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY 13
|
||||
#define BK4819_REG_51_SHIFT_CxCSS_MODE 12
|
||||
#define BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH 11
|
||||
#define BK4819_REG_51_SHIFT_1050HZ_DETECTION 10
|
||||
#define BK4819_REG_51_SHIFT_AUTO_CDCSS_BW 9
|
||||
#define BK4819_REG_51_SHIFT_AUTO_CTCSS_BW 8
|
||||
#define BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1 0
|
||||
|
||||
#define BK4819_REG_51_MASK_ENABLE_CxCSS (0x01U << BK4819_REG_51_SHIFT_ENABLE_CxCSS)
|
||||
#define BK4819_REG_51_MASK_GPIO6_PIN2_INPUT (0x01U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT)
|
||||
#define BK4819_REG_51_MASK_TX_CDCSS_POLARITY (0x01U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY)
|
||||
#define BK4819_REG_51_MASK_CxCSS_MODE (0x01U << BK4819_REG_51_SHIFT_CxCSS_MODE)
|
||||
#define BK4819_REG_51_MASK_CDCSS_BIT_WIDTH (0x01U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH)
|
||||
#define BK4819_REG_51_MASK_1050HZ_DETECTION (0x01U << BK4819_REG_51_SHIFT_1050HZ_DETECTION)
|
||||
#define BK4819_REG_51_MASK_AUTO_CDCSS_BW (0x01U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW)
|
||||
#define BK4819_REG_51_MASK_AUTO_CTCSS_BW (0x01U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW)
|
||||
#define BK4819_REG_51_MASK_CxCSS_TX_GAIN1 (0x7FU << BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1)
|
||||
|
||||
enum {
|
||||
BK4819_REG_51_ENABLE_CxCSS = (1U << BK4819_REG_51_SHIFT_ENABLE_CxCSS),
|
||||
BK4819_REG_51_DISABLE_CxCSS = (0U << BK4819_REG_51_SHIFT_ENABLE_CxCSS),
|
||||
|
||||
BK4819_REG_51_GPIO6_PIN2_INPUT = (1U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT),
|
||||
BK4819_REG_51_GPIO6_PIN2_NORMAL = (0U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT),
|
||||
|
||||
BK4819_REG_51_TX_CDCSS_NEGATIVE = (1U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY),
|
||||
BK4819_REG_51_TX_CDCSS_POSITIVE = (0U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY),
|
||||
|
||||
BK4819_REG_51_MODE_CTCSS = (1U << BK4819_REG_51_SHIFT_CxCSS_MODE),
|
||||
BK4819_REG_51_MODE_CDCSS = (0U << BK4819_REG_51_SHIFT_CxCSS_MODE),
|
||||
|
||||
BK4819_REG_51_CDCSS_24_BIT = (1U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH),
|
||||
BK4819_REG_51_CDCSS_23_BIT = (0U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH),
|
||||
|
||||
BK4819_REG_51_1050HZ_DETECTION = (1U << BK4819_REG_51_SHIFT_1050HZ_DETECTION),
|
||||
BK4819_REG_51_1050HZ_NO_DETECTION = (0U << BK4819_REG_51_SHIFT_1050HZ_DETECTION),
|
||||
|
||||
BK4819_REG_51_AUTO_CDCSS_BW_DISABLE = (1U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW),
|
||||
BK4819_REG_51_AUTO_CDCSS_BW_ENABLE = (0U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW),
|
||||
|
||||
BK4819_REG_51_AUTO_CTCSS_BW_DISABLE = (1U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW),
|
||||
BK4819_REG_51_AUTO_CTCSS_BW_ENABLE = (0U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW),
|
||||
};
|
||||
|
||||
// REG 70
|
||||
|
||||
#define BK4819_REG_70_SHIFT_ENABLE_TONE1 15
|
||||
#define BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN 8
|
||||
#define BK4819_REG_70_SHIFT_ENABLE_TONE2 7
|
||||
#define BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN 0
|
||||
|
||||
#define BK4819_REG_70_MASK_ENABLE_TONE1 (0x01U << BK4819_REG_70_SHIFT_ENABLE_TONE1)
|
||||
#define BK4819_REG_70_MASK_TONE1_TUNING_GAIN (0x7FU << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)
|
||||
#define BK4819_REG_70_MASK_ENABLE_TONE2 (0x01U << BK4819_REG_70_SHIFT_ENABLE_TONE2)
|
||||
#define BK4819_REG_70_MASK_TONE2_TUNING_GAIN (0x7FU << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)
|
||||
|
||||
enum {
|
||||
BK4819_REG_70_ENABLE_TONE1 = (1U << BK4819_REG_70_SHIFT_ENABLE_TONE1),
|
||||
BK4819_REG_70_ENABLE_TONE2 = (1U << BK4819_REG_70_SHIFT_ENABLE_TONE2),
|
||||
};
|
||||
|
||||
#endif
|
||||
|
975
driver/bk4819.c
Normal file
975
driver/bk4819.c
Normal file
@ -0,0 +1,975 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bk4819.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bsp/dp32g030/portcon.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/system.h"
|
||||
#include "driver/systick.h"
|
||||
|
||||
static const uint16_t FSK_RogerTable[7] = {0xF1A2, 0x7446, 0x61A4, 0x6544, 0x4E8A, 0xE044, 0xEA84};
|
||||
|
||||
static uint16_t gBK4819_GpioOutState;
|
||||
|
||||
bool gRxIdleMode;
|
||||
|
||||
__inline uint16_t scale_freq(const uint16_t freq)
|
||||
{
|
||||
// return (uint16_t)(freq * 10.32444); // argh - floating point
|
||||
// return ((uint32_t)freq * 1032444u) / 100000u;
|
||||
return ((uint32_t)freq * 1353245u) >> 17;
|
||||
}
|
||||
|
||||
void BK4819_Init(void)
|
||||
{
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_00, 0x8000);
|
||||
BK4819_WriteRegister(BK4819_REG_00, 0x0000);
|
||||
BK4819_WriteRegister(BK4819_REG_37, 0x1D0F);
|
||||
BK4819_WriteRegister(BK4819_REG_36, 0x0022);
|
||||
BK4819_SetAGC(0);
|
||||
BK4819_WriteRegister(BK4819_REG_19, 0x1041);
|
||||
BK4819_WriteRegister(BK4819_REG_7D, 0xE940);
|
||||
BK4819_WriteRegister(BK4819_REG_48, 0xB3A8);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x006F);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x106B);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x2067);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x3062);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x4050);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x5047);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x603A);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x702C);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x8041);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0x9037);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0xA025);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0xB017);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0xC0E4);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0xD0CB);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0xE0B5);
|
||||
BK4819_WriteRegister(BK4819_REG_09, 0xF09F);
|
||||
BK4819_WriteRegister(BK4819_REG_1F, 0x5454);
|
||||
BK4819_WriteRegister(BK4819_REG_3E, 0xA037);
|
||||
gBK4819_GpioOutState = 0x9000;
|
||||
BK4819_WriteRegister(BK4819_REG_33, 0x9000);
|
||||
BK4819_WriteRegister(BK4819_REG_3F, 0);
|
||||
}
|
||||
|
||||
static uint16_t BK4819_ReadU16(void)
|
||||
{
|
||||
unsigned int i;
|
||||
uint16_t Value;
|
||||
|
||||
PORTCON_PORTC_IE = (PORTCON_PORTC_IE & ~PORTCON_PORTC_IE_C2_MASK) | PORTCON_PORTC_IE_C2_BITS_ENABLE;
|
||||
GPIOC->DIR = (GPIOC->DIR & ~GPIO_DIR_2_MASK) | GPIO_DIR_2_BITS_INPUT;
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
Value = 0;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
Value <<= 1;
|
||||
Value |= GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
PORTCON_PORTC_IE = (PORTCON_PORTC_IE & ~PORTCON_PORTC_IE_C2_MASK) | PORTCON_PORTC_IE_C2_BITS_DISABLE;
|
||||
GPIOC->DIR = (GPIOC->DIR & ~GPIO_DIR_2_MASK) | GPIO_DIR_2_BITS_OUTPUT;
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register)
|
||||
{
|
||||
uint16_t Value;
|
||||
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
|
||||
|
||||
BK4819_WriteU8(Register | 0x80);
|
||||
|
||||
Value = BK4819_ReadU16();
|
||||
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data)
|
||||
{
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
|
||||
BK4819_WriteU8(Register);
|
||||
SYSTICK_DelayUs(1);
|
||||
BK4819_WriteU16(Data);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
|
||||
}
|
||||
|
||||
void BK4819_WriteU8(uint8_t Data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if ((Data & 0x80U) == 0)
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
|
||||
else
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
|
||||
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
Data <<= 1;
|
||||
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
}
|
||||
|
||||
void BK4819_WriteU16(uint16_t Data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
if ((Data & 0x8000U) == 0U)
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
|
||||
else
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
|
||||
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
|
||||
Data <<= 1;
|
||||
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
}
|
||||
|
||||
void BK4819_SetAGC(uint8_t Value)
|
||||
{
|
||||
if (Value == 0)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_13, 0x03BE);
|
||||
BK4819_WriteRegister(BK4819_REG_12, 0x037B);
|
||||
BK4819_WriteRegister(BK4819_REG_11, 0x027B);
|
||||
BK4819_WriteRegister(BK4819_REG_10, 0x007A);
|
||||
BK4819_WriteRegister(BK4819_REG_14, 0x0019);
|
||||
BK4819_WriteRegister(BK4819_REG_49, 0x2A38);
|
||||
BK4819_WriteRegister(BK4819_REG_7B, 0x8420);
|
||||
}
|
||||
else
|
||||
if (Value == 1)
|
||||
{
|
||||
unsigned int i;
|
||||
BK4819_WriteRegister(BK4819_REG_13, 0x03BE);
|
||||
BK4819_WriteRegister(BK4819_REG_12, 0x037C);
|
||||
BK4819_WriteRegister(BK4819_REG_11, 0x027B);
|
||||
BK4819_WriteRegister(BK4819_REG_10, 0x007A);
|
||||
BK4819_WriteRegister(BK4819_REG_14, 0x0018);
|
||||
BK4819_WriteRegister(BK4819_REG_49, 0x2A38);
|
||||
BK4819_WriteRegister(BK4819_REG_7B, 0x318C);
|
||||
BK4819_WriteRegister(BK4819_REG_7C, 0x595E);
|
||||
BK4819_WriteRegister(BK4819_REG_20, 0x8DEF);
|
||||
for (i = 0; i < 8; i++)
|
||||
// Bug? The bit 0x2000 below overwrites the (i << 13)
|
||||
BK4819_WriteRegister(BK4819_REG_06, ((i << 13) | 0x2500u) + 0x036u);
|
||||
}
|
||||
}
|
||||
|
||||
void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet)
|
||||
{
|
||||
if (bSet)
|
||||
gBK4819_GpioOutState |= (0x40u >> Pin);
|
||||
else
|
||||
gBK4819_GpioOutState &= ~(0x40u >> Pin);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_33, gBK4819_GpioOutState);
|
||||
}
|
||||
|
||||
void BK4819_SetCDCSSCodeWord(uint32_t CodeWord)
|
||||
{
|
||||
// Enable CDCSS
|
||||
// Transmit positive CDCSS code
|
||||
// CDCSS Mode
|
||||
// CDCSS 23bit
|
||||
// Enable Auto CDCSS Bw Mode
|
||||
// Enable Auto CTCSS Bw Mode
|
||||
// CTCSS/CDCSS Tx Gain1 Tuning = 51
|
||||
BK4819_WriteRegister(BK4819_REG_51, 0
|
||||
| BK4819_REG_51_ENABLE_CxCSS
|
||||
| BK4819_REG_51_GPIO6_PIN2_NORMAL
|
||||
| BK4819_REG_51_TX_CDCSS_POSITIVE
|
||||
| BK4819_REG_51_MODE_CDCSS
|
||||
| BK4819_REG_51_CDCSS_23_BIT
|
||||
| BK4819_REG_51_1050HZ_NO_DETECTION
|
||||
| BK4819_REG_51_AUTO_CDCSS_BW_ENABLE
|
||||
| BK4819_REG_51_AUTO_CTCSS_BW_ENABLE
|
||||
| (51U << BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1));
|
||||
|
||||
// CTC1 Frequency Control Word = 2775
|
||||
BK4819_WriteRegister(BK4819_REG_07, 0
|
||||
| BK4819_REG_07_MODE_CTC1
|
||||
| (2775u << BK4819_REG_07_SHIFT_FREQUENCY));
|
||||
|
||||
// Set the code word
|
||||
BK4819_WriteRegister(BK4819_REG_08, 0x0000 | ((CodeWord >> 0) & 0xFFF));
|
||||
BK4819_WriteRegister(BK4819_REG_08, 0x8000 | ((CodeWord >> 12) & 0xFFF));
|
||||
}
|
||||
|
||||
void BK4819_SetCTCSSFrequency(uint32_t FreqControlWord)
|
||||
{
|
||||
uint16_t Config;
|
||||
|
||||
if (FreqControlWord == 2625)
|
||||
{ // Enables 1050Hz detection mode
|
||||
// Enable TxCTCSS
|
||||
// CTCSS Mode
|
||||
// 1050/4 Detect Enable
|
||||
// Enable Auto CDCSS Bw Mode
|
||||
// Enable Auto CTCSS Bw Mode
|
||||
// CTCSS/CDCSS Tx Gain1 Tuning = 74
|
||||
Config = 0x944A;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable TxCTCSS
|
||||
// CTCSS Mode
|
||||
// Enable Auto CDCSS Bw Mode
|
||||
// Enable Auto CTCSS Bw Mode
|
||||
// CTCSS/CDCSS Tx Gain1 Tuning = 74
|
||||
Config = 0x904A;
|
||||
}
|
||||
BK4819_WriteRegister(BK4819_REG_51, Config);
|
||||
|
||||
// CTC1 Frequency Control Word
|
||||
BK4819_WriteRegister(BK4819_REG_07, 0
|
||||
| BK4819_REG_07_MODE_CTC1
|
||||
| ((FreqControlWord * 2065) / 1000) << BK4819_REG_07_SHIFT_FREQUENCY);
|
||||
}
|
||||
|
||||
void BK4819_Set55HzTailDetection(void)
|
||||
{
|
||||
// CTC2 Frequency Control Word = round_nearest(25391 / 55) = 462
|
||||
BK4819_WriteRegister(BK4819_REG_07, (1U << 13) | 462);
|
||||
}
|
||||
|
||||
void BK4819_EnableVox(uint16_t VoxEnableThreshold, uint16_t VoxDisableThreshold)
|
||||
{
|
||||
//VOX Algorithm
|
||||
//if (voxamp>VoxEnableThreshold) VOX = 1;
|
||||
//else
|
||||
//if (voxamp<VoxDisableThreshold) (After Delay) VOX = 0;
|
||||
|
||||
const uint16_t REG_31_Value = BK4819_ReadRegister(BK4819_REG_31);
|
||||
|
||||
// 0xA000 is undocumented?
|
||||
BK4819_WriteRegister(BK4819_REG_46, 0xA000 | (VoxEnableThreshold & 0x07FF));
|
||||
|
||||
// 0x1800 is undocumented?
|
||||
BK4819_WriteRegister(BK4819_REG_79, 0x1800 | (VoxDisableThreshold & 0x07FF));
|
||||
|
||||
// Bottom 12 bits are undocumented, 15:12 vox disable delay *128ms
|
||||
BK4819_WriteRegister(BK4819_REG_7A, 0x289A); // vox disable delay = 128*5 = 640ms
|
||||
|
||||
// Enable VOX
|
||||
BK4819_WriteRegister(BK4819_REG_31, REG_31_Value | 4u); // bit 2 - VOX Enable
|
||||
}
|
||||
|
||||
void BK4819_SetFilterBandwidth(BK4819_FilterBandwidth_t Bandwidth)
|
||||
{
|
||||
if (Bandwidth == BK4819_FILTER_BW_WIDE)
|
||||
BK4819_WriteRegister(BK4819_REG_43, 0x3028);
|
||||
else
|
||||
if (Bandwidth == BK4819_FILTER_BW_NARROW)
|
||||
BK4819_WriteRegister(BK4819_REG_43, 0x4048);
|
||||
//BK4819_WriteRegister(BK4819_REG_43, 0x790C); // fastest squelch, https://github.com/fagci/uv-k5-firmware-fagci-mod
|
||||
}
|
||||
|
||||
void BK4819_SetupPowerAmplifier(uint16_t Bias, uint32_t Frequency)
|
||||
{
|
||||
uint8_t Gain;
|
||||
|
||||
if (Bias > 255)
|
||||
Bias = 255;
|
||||
|
||||
if (Frequency < 28000000)
|
||||
{
|
||||
// Gain 1 = 1
|
||||
// Gain 2 = 0
|
||||
Gain = 0x08U;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Gain 1 = 4
|
||||
// Gain 2 = 2
|
||||
Gain = 0x22U;
|
||||
}
|
||||
|
||||
// Enable PACTLoutput
|
||||
BK4819_WriteRegister(BK4819_REG_36, (Bias << 8) | 0x80U | Gain);
|
||||
}
|
||||
|
||||
void BK4819_SetFrequency(uint32_t Frequency)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_38, (Frequency >> 0) & 0xFFFF);
|
||||
BK4819_WriteRegister(BK4819_REG_39, (Frequency >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
void BK4819_SetupSquelch(uint8_t SquelchOpenRSSIThresh, uint8_t SquelchCloseRSSIThresh, uint8_t SquelchOpenNoiseThresh, uint8_t SquelchCloseNoiseThresh, uint8_t SquelchCloseGlitchThresh, uint8_t SquelchOpenGlitchThresh)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0);
|
||||
|
||||
#if 1
|
||||
BK4819_WriteRegister(BK4819_REG_4D, 0xA000 | SquelchCloseGlitchThresh);
|
||||
#else
|
||||
// fastest squelch, https://github.com/fagci/uv-k5-firmware-fagci-mod
|
||||
// this doesn't work !
|
||||
BK4819_WriteRegister(BK4819_REG_4D, 0b01000000 | SquelchCloseGlitchThresh);
|
||||
#endif
|
||||
|
||||
// 0x6f = 0110 1111 meaning the default sql delays from the datasheet are used (101 and 111)
|
||||
BK4819_WriteRegister(BK4819_REG_4E, 0x6F00 | SquelchOpenGlitchThresh);
|
||||
BK4819_WriteRegister(BK4819_REG_4F, (SquelchCloseNoiseThresh << 8) | SquelchOpenNoiseThresh);
|
||||
BK4819_WriteRegister(BK4819_REG_78, (SquelchOpenRSSIThresh << 8) | SquelchCloseRSSIThresh);
|
||||
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
|
||||
BK4819_RX_TurnOn();
|
||||
}
|
||||
|
||||
void BK4819_SetAF(BK4819_AF_Type_t AF)
|
||||
{
|
||||
// AF Output Inverse Mode = Inverse
|
||||
// Undocumented bits 0x2040
|
||||
BK4819_WriteRegister(BK4819_REG_47, 0x6040 | (AF << 8));
|
||||
}
|
||||
|
||||
void BK4819_RX_TurnOn(void)
|
||||
{
|
||||
// DSP Voltage Setting = 1
|
||||
// ANA LDO = 2.7v
|
||||
// VCO LDO = 2.7v
|
||||
// RF LDO = 2.7v
|
||||
// PLL LDO = 2.7v
|
||||
// ANA LDO bypass
|
||||
// VCO LDO bypass
|
||||
// RF LDO bypass
|
||||
// PLL LDO bypass
|
||||
// Reserved bit is 1 instead of 0
|
||||
// Enable DSP
|
||||
// Enable XTAL
|
||||
// Enable Band Gap
|
||||
BK4819_WriteRegister(BK4819_REG_37, 0x1F0F);
|
||||
|
||||
// Turn off everything
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0);
|
||||
|
||||
// Enable VCO Calibration
|
||||
// Enable RX Link
|
||||
// Enable AF DAC
|
||||
// Enable PLL/VCO
|
||||
// Disable PA Gain
|
||||
// Disable MIC ADC
|
||||
// Disable TX DSP
|
||||
// Enable RX DSP
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0xBFF1);
|
||||
}
|
||||
|
||||
void BK4819_PickRXFilterPathBasedOnFrequency(uint32_t Frequency)
|
||||
{
|
||||
if (Frequency < 28000000)
|
||||
{
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO2_PIN30, true);
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31, false);
|
||||
}
|
||||
else
|
||||
if (Frequency == 0xFFFFFFFF)
|
||||
{
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO2_PIN30, false);
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO2_PIN30, false);
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31, true);
|
||||
}
|
||||
}
|
||||
|
||||
void BK4819_DisableScramble(void)
|
||||
{
|
||||
const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31);
|
||||
BK4819_WriteRegister(BK4819_REG_31, Value & 0xFFFD);
|
||||
}
|
||||
|
||||
void BK4819_EnableScramble(uint8_t Type)
|
||||
{
|
||||
const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31);
|
||||
BK4819_WriteRegister(BK4819_REG_31, Value | 2u);
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x68DC + (Type * 1032));
|
||||
}
|
||||
|
||||
void BK4819_DisableVox(void)
|
||||
{
|
||||
const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31);
|
||||
BK4819_WriteRegister(BK4819_REG_31, Value & 0xFFFB);
|
||||
}
|
||||
|
||||
void BK4819_DisableDTMF(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_24, 0);
|
||||
}
|
||||
|
||||
void BK4819_EnableDTMF(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_21, 0x06D8);
|
||||
BK4819_WriteRegister(BK4819_REG_24, 0
|
||||
| (1U << BK4819_REG_24_SHIFT_UNKNOWN_15)
|
||||
| (24 << BK4819_REG_24_SHIFT_THRESHOLD)
|
||||
| (1U << BK4819_REG_24_SHIFT_UNKNOWN_6)
|
||||
| BK4819_REG_24_ENABLE
|
||||
| BK4819_REG_24_SELECT_DTMF
|
||||
| (14U << BK4819_REG_24_SHIFT_MAX_SYMBOLS));
|
||||
}
|
||||
|
||||
void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch)
|
||||
{
|
||||
uint16_t ToneConfig;
|
||||
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_SetAF(BK4819_AF_BEEP);
|
||||
|
||||
if (bTuningGainSwitch == 0)
|
||||
ToneConfig = 0 | BK4819_REG_70_ENABLE_TONE1 | (96U << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN);
|
||||
else
|
||||
ToneConfig = 0 | BK4819_REG_70_ENABLE_TONE1 | (28U << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN);
|
||||
BK4819_WriteRegister(BK4819_REG_70, ToneConfig);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0);
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0
|
||||
| BK4819_REG_30_ENABLE_AF_DAC
|
||||
| BK4819_REG_30_ENABLE_DISC_MODE
|
||||
| BK4819_REG_30_ENABLE_TX_DSP);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency));
|
||||
}
|
||||
|
||||
void BK4819_EnterTxMute(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_50, 0xBB20);
|
||||
}
|
||||
|
||||
void BK4819_ExitTxMute(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_50, 0x3B20);
|
||||
}
|
||||
|
||||
void BK4819_Sleep(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0);
|
||||
BK4819_WriteRegister(BK4819_REG_37, 0x1D00);
|
||||
}
|
||||
|
||||
void BK4819_TurnsOffTones_TurnsOnRX(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0);
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
BK4819_ExitTxMute();
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0);
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0
|
||||
| BK4819_REG_30_ENABLE_VCO_CALIB
|
||||
| BK4819_REG_30_ENABLE_RX_LINK
|
||||
| BK4819_REG_30_ENABLE_AF_DAC
|
||||
| BK4819_REG_30_ENABLE_DISC_MODE
|
||||
| BK4819_REG_30_ENABLE_PLL_VCO
|
||||
| BK4819_REG_30_ENABLE_RX_DSP);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_AIRCOPY
|
||||
void BK4819_SetupAircopy(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0x00E0); // Enable Tone2, tuning gain 48
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x3065); // Tone2 baudrate 1200
|
||||
BK4819_WriteRegister(BK4819_REG_58, 0x00C1); // FSK Enable, FSK 1.2K RX Bandwidth, Preamble 0xAA or 0x55, RX Gain 0, RX Mode
|
||||
// (FSK1.2K, FSK2.4K Rx and NOAA SAME Rx), TX Mode FSK 1.2K and FSK 2.4K Tx
|
||||
BK4819_WriteRegister(BK4819_REG_5C, 0x5665); // Enable CRC among other things we don't know yet
|
||||
BK4819_WriteRegister(BK4819_REG_5D, 0x4700); // FSK Data Length 72 Bytes (0xabcd + 2 byte length + 64 byte payload + 2 byte CRC + 0xdcba)
|
||||
}
|
||||
#endif
|
||||
|
||||
void BK4819_ResetFSK(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_3F, 0x0000); // Disable interrupts
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x0068); // Sync length 4 bytes, 7 byte preamble
|
||||
SYSTEM_DelayMs(30);
|
||||
BK4819_Idle();
|
||||
}
|
||||
|
||||
void BK4819_Idle(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0x0000);
|
||||
}
|
||||
|
||||
void BK4819_ExitBypass(void)
|
||||
{
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
BK4819_WriteRegister(BK4819_REG_7E, 0x302E);
|
||||
}
|
||||
|
||||
void BK4819_PrepareTransmit(void)
|
||||
{
|
||||
BK4819_ExitBypass();
|
||||
BK4819_ExitTxMute();
|
||||
BK4819_TxOn_Beep();
|
||||
}
|
||||
|
||||
void BK4819_TxOn_Beep(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_37, 0x1D0F);
|
||||
BK4819_WriteRegister(BK4819_REG_52, 0x028F);
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0x0000);
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE);
|
||||
}
|
||||
|
||||
void BK4819_ExitSubAu(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_51, 0x0000);
|
||||
}
|
||||
|
||||
void BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(void)
|
||||
{
|
||||
if (gRxIdleMode)
|
||||
{
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2, true);
|
||||
BK4819_RX_TurnOn();
|
||||
}
|
||||
}
|
||||
|
||||
void BK4819_EnterDTMF_TX(bool bLocalLoopback)
|
||||
{
|
||||
BK4819_EnableDTMF();
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE);
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0
|
||||
| BK4819_REG_70_MASK_ENABLE_TONE1
|
||||
| (83 << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)
|
||||
| BK4819_REG_70_MASK_ENABLE_TONE2
|
||||
| (83 << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN));
|
||||
|
||||
BK4819_EnableTXLink();
|
||||
}
|
||||
|
||||
void BK4819_ExitDTMF_TX(bool bKeep)
|
||||
{
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0x0000);
|
||||
BK4819_DisableDTMF();
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE);
|
||||
if (!bKeep)
|
||||
BK4819_ExitTxMute();
|
||||
}
|
||||
|
||||
void BK4819_EnableTXLink(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0
|
||||
| BK4819_REG_30_ENABLE_VCO_CALIB
|
||||
| BK4819_REG_30_ENABLE_UNKNOWN
|
||||
| BK4819_REG_30_DISABLE_RX_LINK
|
||||
| BK4819_REG_30_ENABLE_AF_DAC
|
||||
| BK4819_REG_30_ENABLE_DISC_MODE
|
||||
| BK4819_REG_30_ENABLE_PLL_VCO
|
||||
| BK4819_REG_30_ENABLE_PA_GAIN
|
||||
| BK4819_REG_30_DISABLE_MIC_ADC
|
||||
| BK4819_REG_30_ENABLE_TX_DSP
|
||||
| BK4819_REG_30_DISABLE_RX_DSP);
|
||||
}
|
||||
|
||||
void BK4819_PlayDTMF(char Code)
|
||||
{
|
||||
switch (Code)
|
||||
{
|
||||
case '0':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x25F3);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x35E1);
|
||||
break;
|
||||
case '1':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1C1C);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x30C2);
|
||||
break;
|
||||
case '2':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1C1C);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x35E1);
|
||||
break;
|
||||
case '3':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1C1C);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x3B91);
|
||||
break;
|
||||
case '4':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1F0E);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x30C2);
|
||||
break;
|
||||
case '5':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1F0E);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x35E1);
|
||||
break;
|
||||
case '6':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1F0E);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x3B91);
|
||||
break;
|
||||
case '7':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x225C);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x30C2);
|
||||
break;
|
||||
case '8':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x225c);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x35E1);
|
||||
break;
|
||||
case '9':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x225C);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x3B91);
|
||||
break;
|
||||
case 'A':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1C1C);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x41DC);
|
||||
break;
|
||||
case 'B':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1F0E);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x41DC);
|
||||
break;
|
||||
case 'C':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x225C);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x41DC);
|
||||
break;
|
||||
case 'D':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x25F3);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x41DC);
|
||||
break;
|
||||
case '*':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x25F3);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x30C2);
|
||||
break;
|
||||
case '#':
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x25F3);
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x3B91);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BK4819_PlayDTMFString(const char *pString, bool bDelayFirst, uint16_t FirstCodePersistTime, uint16_t HashCodePersistTime, uint16_t CodePersistTime, uint16_t CodeInternalTime)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; pString[i]; i++)
|
||||
{
|
||||
uint16_t Delay;
|
||||
BK4819_PlayDTMF(pString[i]);
|
||||
BK4819_ExitTxMute();
|
||||
if (bDelayFirst && i == 0)
|
||||
Delay = FirstCodePersistTime;
|
||||
else
|
||||
if (pString[i] == '*' || pString[i] == '#')
|
||||
Delay = HashCodePersistTime;
|
||||
else
|
||||
Delay = CodePersistTime;
|
||||
SYSTEM_DelayMs(Delay);
|
||||
BK4819_EnterTxMute();
|
||||
SYSTEM_DelayMs(CodeInternalTime);
|
||||
}
|
||||
}
|
||||
|
||||
void BK4819_TransmitTone(bool bLocalLoopback, uint32_t Frequency)
|
||||
{
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0 | BK4819_REG_70_MASK_ENABLE_TONE1 | (96U << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
|
||||
BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency));
|
||||
BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE);
|
||||
BK4819_EnableTXLink();
|
||||
SYSTEM_DelayMs(50);
|
||||
BK4819_ExitTxMute();
|
||||
}
|
||||
|
||||
void BK4819_GenTail(uint8_t Tail)
|
||||
{
|
||||
switch (Tail)
|
||||
{
|
||||
case 0: // CTC134
|
||||
BK4819_WriteRegister(BK4819_REG_52, 0x828F);
|
||||
break;
|
||||
case 1: // CTC120
|
||||
BK4819_WriteRegister(BK4819_REG_52, 0xA28F);
|
||||
break;
|
||||
case 2: // CTC180
|
||||
BK4819_WriteRegister(BK4819_REG_52, 0xC28F);
|
||||
break;
|
||||
case 3: // CTC240
|
||||
BK4819_WriteRegister(BK4819_REG_52, 0xE28F);
|
||||
break;
|
||||
case 4: // CTC55
|
||||
BK4819_WriteRegister(BK4819_REG_07, 0x046f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BK4819_EnableCDCSS(void)
|
||||
{
|
||||
BK4819_GenTail(0); // CTC134
|
||||
BK4819_WriteRegister(BK4819_REG_51, 0x804A);
|
||||
}
|
||||
|
||||
void BK4819_EnableCTCSS(void)
|
||||
{
|
||||
BK4819_GenTail(4); // CTC55
|
||||
BK4819_WriteRegister(BK4819_REG_51, 0x904A);
|
||||
}
|
||||
|
||||
uint16_t BK4819_GetRSSI(void)
|
||||
{
|
||||
return BK4819_ReadRegister(BK4819_REG_67) & 0x01FF;
|
||||
}
|
||||
|
||||
bool BK4819_GetFrequencyScanResult(uint32_t *pFrequency)
|
||||
{
|
||||
const uint16_t High = BK4819_ReadRegister(BK4819_REG_0D);
|
||||
const bool Finished = (High & 0x8000) == 0;
|
||||
if (Finished)
|
||||
{
|
||||
const uint16_t Low = BK4819_ReadRegister(BK4819_REG_0E);
|
||||
*pFrequency = (uint32_t)((High & 0x7FF) << 16) | Low;
|
||||
}
|
||||
return Finished;
|
||||
}
|
||||
|
||||
BK4819_CssScanResult_t BK4819_GetCxCSSScanResult(uint32_t *pCdcssFreq, uint16_t *pCtcssFreq)
|
||||
{
|
||||
uint16_t Low;
|
||||
uint16_t High = BK4819_ReadRegister(BK4819_REG_69);
|
||||
|
||||
if ((High & 0x8000) == 0)
|
||||
{
|
||||
Low = BK4819_ReadRegister(BK4819_REG_6A);
|
||||
*pCdcssFreq = ((High & 0xFFF) << 12) | (Low & 0xFFF);
|
||||
return BK4819_CSS_RESULT_CDCSS;
|
||||
}
|
||||
|
||||
Low = BK4819_ReadRegister(BK4819_REG_68);
|
||||
|
||||
if ((Low & 0x8000) == 0)
|
||||
{
|
||||
*pCtcssFreq = ((Low & 0x1FFF) * 4843) / 10000;
|
||||
return BK4819_CSS_RESULT_CTCSS;
|
||||
}
|
||||
|
||||
return BK4819_CSS_RESULT_NOT_FOUND;
|
||||
}
|
||||
|
||||
void BK4819_DisableFrequencyScan(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_32, 0x0244);
|
||||
}
|
||||
|
||||
void BK4819_EnableFrequencyScan(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_32, 0x0245);
|
||||
}
|
||||
|
||||
void BK4819_SetScanFrequency(uint32_t Frequency)
|
||||
{
|
||||
BK4819_SetFrequency(Frequency);
|
||||
BK4819_WriteRegister(BK4819_REG_51, 0
|
||||
| BK4819_REG_51_DISABLE_CxCSS
|
||||
| BK4819_REG_51_GPIO6_PIN2_NORMAL
|
||||
| BK4819_REG_51_TX_CDCSS_POSITIVE
|
||||
| BK4819_REG_51_MODE_CDCSS
|
||||
| BK4819_REG_51_CDCSS_23_BIT
|
||||
| BK4819_REG_51_1050HZ_NO_DETECTION
|
||||
| BK4819_REG_51_AUTO_CDCSS_BW_DISABLE
|
||||
| BK4819_REG_51_AUTO_CTCSS_BW_DISABLE);
|
||||
BK4819_RX_TurnOn();
|
||||
}
|
||||
|
||||
void BK4819_Disable(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0);
|
||||
}
|
||||
|
||||
void BK4819_StopScan(void)
|
||||
{
|
||||
BK4819_DisableFrequencyScan();
|
||||
BK4819_Disable();
|
||||
}
|
||||
|
||||
uint8_t BK4819_GetDTMF_5TONE_Code(void)
|
||||
{
|
||||
return (BK4819_ReadRegister(BK4819_REG_0B) >> 8) & 0x0F;
|
||||
}
|
||||
|
||||
uint8_t BK4819_GetCDCSSCodeType(void)
|
||||
{
|
||||
return (BK4819_ReadRegister(BK4819_REG_0C) >> 14) & 3;
|
||||
}
|
||||
|
||||
uint8_t BK4819_GetCTCType(void)
|
||||
{
|
||||
return (BK4819_ReadRegister(BK4819_REG_0C) >> 10) & 3;
|
||||
}
|
||||
|
||||
void BK4819_SendFSKData(uint16_t *pData)
|
||||
{
|
||||
unsigned int i;
|
||||
uint8_t Timeout = 200;
|
||||
|
||||
SYSTEM_DelayMs(20);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_3F, BK4819_REG_3F_FSK_TX_FINISHED);
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x8068);
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x0068);
|
||||
|
||||
for (i = 0; i < 36; i++)
|
||||
BK4819_WriteRegister(BK4819_REG_5F, pData[i]);
|
||||
|
||||
SYSTEM_DelayMs(20);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x2868);
|
||||
|
||||
while (Timeout-- && (BK4819_ReadRegister(BK4819_REG_0C) & 1u) == 0)
|
||||
SYSTEM_DelayMs(5);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_02, 0);
|
||||
|
||||
SYSTEM_DelayMs(20);
|
||||
|
||||
BK4819_ResetFSK();
|
||||
}
|
||||
|
||||
void BK4819_PrepareFSKReceive(void)
|
||||
{
|
||||
BK4819_ResetFSK();
|
||||
BK4819_WriteRegister(BK4819_REG_02, 0);
|
||||
BK4819_WriteRegister(BK4819_REG_3F, 0);
|
||||
BK4819_RX_TurnOn();
|
||||
BK4819_WriteRegister(BK4819_REG_3F, 0 | BK4819_REG_3F_FSK_RX_FINISHED | BK4819_REG_3F_FSK_FIFO_ALMOST_FULL);
|
||||
|
||||
// Clear RX FIFO
|
||||
// FSK Preamble Length 7 bytes
|
||||
// FSK SyncLength Selection
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x4068);
|
||||
|
||||
// Enable FSK Scramble
|
||||
// Enable FSK RX
|
||||
// FSK Preamble Length 7 bytes
|
||||
// FSK SyncLength Selection
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x3068);
|
||||
}
|
||||
|
||||
void BK4819_PlayRoger(void)
|
||||
{
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0xE000);
|
||||
BK4819_EnableTXLink();
|
||||
SYSTEM_DelayMs(50);
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x142A);
|
||||
BK4819_ExitTxMute();
|
||||
SYSTEM_DelayMs(80);
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_WriteRegister(BK4819_REG_71, 0x1C3B);
|
||||
BK4819_ExitTxMute();
|
||||
SYSTEM_DelayMs(80);
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0x0000);
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE);
|
||||
}
|
||||
|
||||
void BK4819_PlayRogerMDC(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
BK4819_WriteRegister(BK4819_REG_58, 0x37C3); // FSK Enable, RX Bandwidth FFSK1200/1800, 0xAA or 0x55 Preamble, 11 RX Gain,
|
||||
// 101 RX Mode, FFSK1200/1800 TX
|
||||
BK4819_WriteRegister(BK4819_REG_72, 0x3065); // Set Tone2 to 1200Hz
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0x00E0); // Enable Tone2 and Set Tone2 Gain
|
||||
BK4819_WriteRegister(BK4819_REG_5D, 0x0D00); // Set FSK data length to 13 bytes
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x8068); // 4 byte sync length, 6 byte preamble, clear TX FIFO
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x0068); // Same, but clear TX FIFO is now unset (clearing done)
|
||||
BK4819_WriteRegister(BK4819_REG_5A, 0x5555); // First two sync bytes
|
||||
BK4819_WriteRegister(BK4819_REG_5B, 0x55AA); // End of sync bytes. Total 4 bytes: 555555aa
|
||||
BK4819_WriteRegister(BK4819_REG_5C, 0xAA30); // Disable CRC
|
||||
|
||||
// Send the data from the roger table
|
||||
for (i = 0; i < 7; i++)
|
||||
BK4819_WriteRegister(BK4819_REG_5F, FSK_RogerTable[i]);
|
||||
|
||||
SYSTEM_DelayMs(20);
|
||||
|
||||
// 4 sync bytes, 6 byte preamble, Enable FSK TX
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x0868);
|
||||
|
||||
SYSTEM_DelayMs(180);
|
||||
|
||||
// Stop FSK TX, reset Tone2, disable FSK
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x0068);
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0x0000);
|
||||
BK4819_WriteRegister(BK4819_REG_58, 0x0000);
|
||||
}
|
||||
|
||||
void BK4819_Enable_AfDac_DiscMode_TxDsp(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0x0000);
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0x0302);
|
||||
}
|
||||
|
||||
void BK4819_GetVoxAmp(uint16_t *pResult)
|
||||
{
|
||||
*pResult = BK4819_ReadRegister(BK4819_REG_64) & 0x7FFF;
|
||||
}
|
||||
|
||||
void BK4819_SetScrambleFrequencyControlWord(uint32_t Frequency)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency));
|
||||
}
|
||||
|
||||
void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code)
|
||||
{
|
||||
BK4819_EnableDTMF();
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE);
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0xD3D3);
|
||||
BK4819_EnableTXLink();
|
||||
SYSTEM_DelayMs(50);
|
||||
BK4819_PlayDTMF(Code);
|
||||
BK4819_ExitTxMute();
|
||||
}
|
150
driver/bk4819.h
Normal file
150
driver/bk4819.h
Normal file
@ -0,0 +1,150 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_BK4819_h
|
||||
#define DRIVER_BK4819_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "driver/bk4819-regs.h"
|
||||
|
||||
enum BK4819_AF_Type_t
|
||||
{
|
||||
BK4819_AF_MUTE = 0U,
|
||||
BK4819_AF_OPEN = 1U,
|
||||
BK4819_AF_ALAM = 2U,
|
||||
BK4819_AF_BEEP = 3U,
|
||||
BK4819_AF_CTCO = 6U,
|
||||
BK4819_AF_AM = 7U,
|
||||
BK4819_AF_FSKO = 8U,
|
||||
};
|
||||
|
||||
typedef enum BK4819_AF_Type_t BK4819_AF_Type_t;
|
||||
|
||||
enum BK4819_FilterBandwidth_t
|
||||
{
|
||||
BK4819_FILTER_BW_WIDE = 0U,
|
||||
BK4819_FILTER_BW_NARROW = 1U,
|
||||
};
|
||||
|
||||
typedef enum BK4819_FilterBandwidth_t BK4819_FilterBandwidth_t;
|
||||
|
||||
enum BK4819_CssScanResult_t
|
||||
{
|
||||
BK4819_CSS_RESULT_NOT_FOUND = 0U,
|
||||
BK4819_CSS_RESULT_CTCSS = 1U,
|
||||
BK4819_CSS_RESULT_CDCSS = 2U,
|
||||
};
|
||||
|
||||
typedef enum BK4819_CssScanResult_t BK4819_CssScanResult_t;
|
||||
|
||||
extern bool gRxIdleMode;
|
||||
|
||||
void BK4819_Init(void);
|
||||
uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register);
|
||||
void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data);
|
||||
void BK4819_WriteU8(uint8_t Data);
|
||||
void BK4819_WriteU16(uint16_t Data);
|
||||
|
||||
void BK4819_SetAGC(uint8_t Value);
|
||||
|
||||
void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet);
|
||||
|
||||
void BK4819_SetCDCSSCodeWord(uint32_t CodeWord);
|
||||
void BK4819_SetCTCSSFrequency(uint32_t BaudRate);
|
||||
void BK4819_Set55HzTailDetection(void);
|
||||
void BK4819_EnableVox(uint16_t Vox1Threshold, uint16_t Vox0Threshold);
|
||||
void BK4819_SetFilterBandwidth(BK4819_FilterBandwidth_t Bandwidth);
|
||||
void BK4819_SetupPowerAmplifier(uint16_t Bias, uint32_t Frequency);
|
||||
void BK4819_SetFrequency(uint32_t Frequency);
|
||||
void BK4819_SetupSquelch(
|
||||
uint8_t SquelchOpenRSSIThresh,
|
||||
uint8_t SquelchCloseRSSIThresh,
|
||||
uint8_t SquelchOpenNoiseThresh,
|
||||
uint8_t SquelchCloseNoiseThresh,
|
||||
uint8_t SquelchCloseGlitchThresh,
|
||||
uint8_t SquelchOpenGlitchThresh);
|
||||
|
||||
void BK4819_SetAF(BK4819_AF_Type_t AF);
|
||||
void BK4819_RX_TurnOn(void);
|
||||
void BK4819_PickRXFilterPathBasedOnFrequency(uint32_t Frequency);
|
||||
void BK4819_DisableScramble(void);
|
||||
void BK4819_EnableScramble(uint8_t Type);
|
||||
void BK4819_DisableVox(void);
|
||||
void BK4819_DisableDTMF(void);
|
||||
void BK4819_EnableDTMF(void);
|
||||
void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch);
|
||||
void BK4819_EnterTxMute(void);
|
||||
void BK4819_ExitTxMute(void);
|
||||
void BK4819_Sleep(void);
|
||||
void BK4819_TurnsOffTones_TurnsOnRX(void);
|
||||
#ifndef DISABLE_AIRCOPY
|
||||
void BK4819_SetupAircopy(void);
|
||||
#endif
|
||||
void BK4819_ResetFSK(void);
|
||||
void BK4819_Idle(void);
|
||||
void BK4819_ExitBypass(void);
|
||||
void BK4819_PrepareTransmit(void);
|
||||
void BK4819_TxOn_Beep(void);
|
||||
void BK4819_ExitSubAu(void);
|
||||
|
||||
void BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(void);
|
||||
|
||||
void BK4819_EnterDTMF_TX(bool bLocalLoopback);
|
||||
void BK4819_ExitDTMF_TX(bool bKeep);
|
||||
void BK4819_EnableTXLink(void);
|
||||
|
||||
void BK4819_PlayDTMF(char Code);
|
||||
void BK4819_PlayDTMFString(const char *pString, bool bDelayFirst, uint16_t FirstCodePersistTime, uint16_t HashCodePersistTime, uint16_t CodePersistTime, uint16_t CodeInternalTime);
|
||||
|
||||
void BK4819_TransmitTone(bool bLocalLoopback, uint32_t Frequency);
|
||||
|
||||
void BK4819_GenTail(uint8_t Tail);
|
||||
void BK4819_EnableCDCSS(void);
|
||||
void BK4819_EnableCTCSS(void);
|
||||
|
||||
uint16_t BK4819_GetRSSI(void);
|
||||
|
||||
bool BK4819_GetFrequencyScanResult(uint32_t *pFrequency);
|
||||
BK4819_CssScanResult_t BK4819_GetCxCSSScanResult(uint32_t *pCdcssFreq, uint16_t *pCtcssFreq);
|
||||
void BK4819_DisableFrequencyScan(void);
|
||||
void BK4819_EnableFrequencyScan(void);
|
||||
void BK4819_SetScanFrequency(uint32_t Frequency);
|
||||
|
||||
void BK4819_Disable(void);
|
||||
|
||||
void BK4819_StopScan(void);
|
||||
|
||||
uint8_t BK4819_GetDTMF_5TONE_Code(void);
|
||||
|
||||
uint8_t BK4819_GetCDCSSCodeType(void);
|
||||
uint8_t BK4819_GetCTCType(void);
|
||||
|
||||
void BK4819_SendFSKData(uint16_t *pData);
|
||||
void BK4819_PrepareFSKReceive(void);
|
||||
|
||||
void BK4819_PlayRoger(void);
|
||||
void BK4819_PlayRogerMDC(void);
|
||||
|
||||
void BK4819_Enable_AfDac_DiscMode_TxDsp(void);
|
||||
|
||||
void BK4819_GetVoxAmp(uint16_t *pResult);
|
||||
void BK4819_SetScrambleFrequencyControlWord(uint32_t Frequency);
|
||||
void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code);
|
||||
|
||||
#endif
|
||||
|
50
driver/crc.c
Normal file
50
driver/crc.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bsp/dp32g030/crc.h"
|
||||
#include "driver/crc.h"
|
||||
|
||||
void CRC_Init(void)
|
||||
{
|
||||
CRC_CR = 0
|
||||
| CRC_CR_CRC_EN_BITS_DISABLE
|
||||
| CRC_CR_INPUT_REV_BITS_NORMAL
|
||||
| CRC_CR_INPUT_INV_BITS_NORMAL
|
||||
| CRC_CR_OUTPUT_REV_BITS_NORMAL
|
||||
| CRC_CR_OUTPUT_INV_BITS_NORMAL
|
||||
| CRC_CR_DATA_WIDTH_BITS_8
|
||||
| CRC_CR_CRC_SEL_BITS_CRC_16_CCITT
|
||||
;
|
||||
CRC_IV = 0;
|
||||
}
|
||||
|
||||
uint16_t CRC_Calculate(const void *pBuffer, uint16_t Size)
|
||||
{
|
||||
const uint8_t *pData = (const uint8_t *)pBuffer;
|
||||
uint16_t i, Crc;
|
||||
|
||||
CRC_CR = (CRC_CR & ~CRC_CR_CRC_EN_MASK) | CRC_CR_CRC_EN_BITS_ENABLE;
|
||||
|
||||
for (i = 0; i < Size; i++) {
|
||||
CRC_DATAIN = pData[i];
|
||||
}
|
||||
Crc = (uint16_t)CRC_DATAOUT;
|
||||
|
||||
CRC_CR = (CRC_CR & ~CRC_CR_CRC_EN_MASK) | CRC_CR_CRC_EN_BITS_DISABLE;
|
||||
|
||||
return Crc;
|
||||
}
|
||||
|
26
driver/crc.h
Normal file
26
driver/crc.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_CRC_H
|
||||
#define DRIVER_CRC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void CRC_Init(void);
|
||||
uint16_t CRC_Calculate(const void *pBuffer, uint16_t Size);
|
||||
|
||||
#endif
|
||||
|
55
driver/eeprom.c
Normal file
55
driver/eeprom.c
Normal file
@ -0,0 +1,55 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "driver/eeprom.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/system.h"
|
||||
|
||||
void EEPROM_ReadBuffer(uint16_t Address, void *pBuffer, uint8_t Size)
|
||||
{
|
||||
I2C_Start();
|
||||
|
||||
I2C_Write(0xA0);
|
||||
|
||||
I2C_Write((Address >> 8) & 0xFF);
|
||||
I2C_Write((Address >> 0) & 0xFF);
|
||||
|
||||
I2C_Start();
|
||||
|
||||
I2C_Write(0xA1);
|
||||
|
||||
I2C_ReadBuffer(pBuffer, Size);
|
||||
|
||||
I2C_Stop();
|
||||
}
|
||||
|
||||
void EEPROM_WriteBuffer(uint16_t Address, const void *pBuffer)
|
||||
|
||||
{
|
||||
I2C_Start();
|
||||
|
||||
I2C_Write(0xA0);
|
||||
|
||||
I2C_Write((Address >> 8) & 0xFF);
|
||||
I2C_Write((Address >> 0) & 0xFF);
|
||||
|
||||
I2C_WriteBuffer(pBuffer, 8);
|
||||
|
||||
I2C_Stop();
|
||||
|
||||
SYSTEM_DelayMs(10);
|
||||
}
|
||||
|
26
driver/eeprom.h
Normal file
26
driver/eeprom.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_EEPROM_H
|
||||
#define DRIVER_EEPROM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void EEPROM_ReadBuffer(uint16_t Address, void *pBuffer, uint8_t Size);
|
||||
void EEPROM_WriteBuffer(uint16_t Address, const void *pBuffer);
|
||||
|
||||
#endif
|
||||
|
34
driver/flash.c
Normal file
34
driver/flash.c
Normal file
@ -0,0 +1,34 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "driver/flash.h"
|
||||
#include "sram-overlay.h"
|
||||
|
||||
void FLASH_Init(FLASH_READ_MODE ReadMode)
|
||||
{
|
||||
overlay_FLASH_Init(ReadMode);
|
||||
}
|
||||
|
||||
void FLASH_ConfigureTrimValues(void)
|
||||
{
|
||||
overlay_FLASH_ConfigureTrimValues();
|
||||
}
|
||||
|
||||
uint32_t FLASH_ReadNvrWord(uint32_t Address)
|
||||
{
|
||||
return overlay_FLASH_ReadNvrWord(Address);
|
||||
}
|
||||
|
59
driver/flash.h
Normal file
59
driver/flash.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_FLASH_H
|
||||
#define DRIVER_FLASH_H
|
||||
|
||||
#include "bsp/dp32g030/flash.h"
|
||||
|
||||
enum FLASH_READ_MODE {
|
||||
FLASH_READ_MODE_1_CYCLE = FLASH_CFG_READ_MD_VALUE_1_CYCLE,
|
||||
FLASH_READ_MODE_2_CYCLE = FLASH_CFG_READ_MD_VALUE_2_CYCLE,
|
||||
};
|
||||
|
||||
typedef enum FLASH_READ_MODE FLASH_READ_MODE;
|
||||
|
||||
enum FLASH_MASK_SELECTION {
|
||||
FLASH_MASK_SELECTION_NONE = FLASH_MASK_SEL_VALUE_NONE,
|
||||
FLASH_MASK_SELECTION_2KB = FLASH_MASK_SEL_VALUE_2KB,
|
||||
FLASH_MASK_SELECTION_4KB = FLASH_MASK_SEL_VALUE_4KB,
|
||||
FLASH_MASK_SELECTION_8KB = FLASH_MASK_SEL_VALUE_8KB,
|
||||
};
|
||||
|
||||
typedef enum FLASH_MASK_SELECTION FLASH_MASK_SELECTION;
|
||||
|
||||
enum FLASH_MODE {
|
||||
FLASH_MODE_READ_AHB = FLASH_CFG_MODE_VALUE_READ_AHB,
|
||||
FLASH_MODE_PROGRAM = FLASH_CFG_MODE_VALUE_PROGRAM,
|
||||
FLASH_MODE_ERASE = FLASH_CFG_MODE_VALUE_ERASE,
|
||||
FLASH_MODE_READ_APB = FLASH_CFG_MODE_VALUE_READ_APB,
|
||||
};
|
||||
|
||||
typedef enum FLASH_MODE FLASH_MODE;
|
||||
|
||||
enum FLASH_AREA {
|
||||
FLASH_AREA_MAIN = FLASH_CFG_NVR_SEL_VALUE_MAIN,
|
||||
FLASH_AREA_NVR = FLASH_CFG_NVR_SEL_VALUE_NVR,
|
||||
};
|
||||
|
||||
typedef enum FLASH_AREA FLASH_AREA;
|
||||
|
||||
void FLASH_Init(FLASH_READ_MODE ReadMode);
|
||||
void FLASH_ConfigureTrimValues(void);
|
||||
uint32_t FLASH_ReadNvrWord(uint32_t Address);
|
||||
|
||||
#endif
|
||||
|
38
driver/gpio.c
Normal file
38
driver/gpio.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "driver/gpio.h"
|
||||
|
||||
void GPIO_ClearBit(volatile uint32_t *pReg, uint8_t Bit)
|
||||
{
|
||||
*pReg &= ~(1U << Bit);
|
||||
}
|
||||
|
||||
uint8_t GPIO_CheckBit(volatile uint32_t *pReg, uint8_t Bit)
|
||||
{
|
||||
return (*pReg >> Bit) & 1U;
|
||||
}
|
||||
|
||||
void GPIO_FlipBit(volatile uint32_t *pReg, uint8_t Bit)
|
||||
{
|
||||
*pReg ^= 1U << Bit;
|
||||
}
|
||||
|
||||
void GPIO_SetBit(volatile uint32_t *pReg, uint8_t Bit)
|
||||
{
|
||||
*pReg |= 1U << Bit;
|
||||
}
|
||||
|
69
driver/gpio.h
Normal file
69
driver/gpio.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_GPIO_H
|
||||
#define DRIVER_GPIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum GPIOA_PINS {
|
||||
GPIOA_PIN_KEYBOARD_0 = 3,
|
||||
GPIOA_PIN_KEYBOARD_1 = 4,
|
||||
GPIOA_PIN_KEYBOARD_2 = 5,
|
||||
GPIOA_PIN_KEYBOARD_3 = 6,
|
||||
GPIOA_PIN_KEYBOARD_4 = 10, // Shared with I2C!
|
||||
GPIOA_PIN_KEYBOARD_5 = 11, // Shared with I2C!
|
||||
GPIOA_PIN_KEYBOARD_6 = 12, // Shared with voice chip!
|
||||
GPIOA_PIN_KEYBOARD_7 = 13, // Shared with voice chip!
|
||||
|
||||
GPIOA_PIN_I2C_SCL = 10, // Shared with keyboard!
|
||||
GPIOA_PIN_I2C_SDA = 11, // Shared with keyboard!
|
||||
|
||||
GPIOA_PIN_VOICE_0 = 12, // Shared with keyboard!
|
||||
GPIOA_PIN_VOICE_1 = 13, // Shared with keyboard!
|
||||
};
|
||||
|
||||
enum GPIOB_PINS {
|
||||
GPIOB_PIN_BACKLIGHT = 6,
|
||||
|
||||
GPIOB_PIN_ST7565_A0 = 9,
|
||||
GPIOB_PIN_ST7565_RES = 11, // Shared with SWD!
|
||||
|
||||
GPIOB_PIN_SWD_IO = 11, // Shared with ST7565!
|
||||
GPIOB_PIN_SWD_CLK = 14,
|
||||
|
||||
GPIOB_PIN_BK1080 = 15,
|
||||
};
|
||||
|
||||
enum GPIOC_PINS {
|
||||
GPIOC_PIN_BK4819_SCN = 0,
|
||||
GPIOC_PIN_BK4819_SCL = 1,
|
||||
GPIOC_PIN_BK4819_SDA = 2,
|
||||
|
||||
GPIOC_PIN_FLASHLIGHT = 3,
|
||||
|
||||
GPIOC_PIN_AUDIO_PATH = 4,
|
||||
|
||||
GPIOC_PIN_PTT = 5,
|
||||
};
|
||||
|
||||
void GPIO_ClearBit(volatile uint32_t *pReg, uint8_t Bit);
|
||||
uint8_t GPIO_CheckBit(volatile uint32_t *pReg, uint8_t Bit);
|
||||
void GPIO_FlipBit(volatile uint32_t *pReg, uint8_t Bit);
|
||||
void GPIO_SetBit(volatile uint32_t *pReg, uint8_t Bit);
|
||||
|
||||
#endif
|
||||
|
169
driver/i2c.c
Normal file
169
driver/i2c.c
Normal file
@ -0,0 +1,169 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bsp/dp32g030/portcon.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/systick.h"
|
||||
|
||||
void I2C_Start(void)
|
||||
{
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
|
||||
void I2C_Stop(void)
|
||||
{
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
|
||||
uint8_t I2C_Read(bool bFinal)
|
||||
{
|
||||
uint8_t i, Data;
|
||||
|
||||
PORTCON_PORTA_IE |= PORTCON_PORTA_IE_A11_BITS_ENABLE;
|
||||
PORTCON_PORTA_OD &= ~PORTCON_PORTA_OD_A11_MASK;
|
||||
GPIOA->DIR &= ~GPIO_DIR_11_MASK;
|
||||
|
||||
Data = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
Data <<= 1;
|
||||
SYSTICK_DelayUs(1);
|
||||
if (GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA)) {
|
||||
Data |= 1U;
|
||||
}
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
|
||||
PORTCON_PORTA_IE &= ~PORTCON_PORTA_IE_A11_MASK;
|
||||
PORTCON_PORTA_OD |= PORTCON_PORTA_OD_A11_BITS_ENABLE;
|
||||
GPIOA->DIR |= GPIO_DIR_11_BITS_OUTPUT;
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
if (bFinal) {
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
} else {
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
}
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
return Data;
|
||||
}
|
||||
|
||||
int I2C_Write(uint8_t Data)
|
||||
{
|
||||
uint8_t i;
|
||||
int ret = -1;
|
||||
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((Data & 0x80) == 0) {
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
} else {
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
}
|
||||
Data <<= 1;
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
|
||||
PORTCON_PORTA_IE |= PORTCON_PORTA_IE_A11_BITS_ENABLE;
|
||||
PORTCON_PORTA_OD &= ~PORTCON_PORTA_OD_A11_MASK;
|
||||
GPIOA->DIR &= ~GPIO_DIR_11_MASK;
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
if (GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA) == 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
PORTCON_PORTA_IE &= ~PORTCON_PORTA_IE_A11_MASK;
|
||||
PORTCON_PORTA_OD |= PORTCON_PORTA_OD_A11_BITS_ENABLE;
|
||||
GPIOA->DIR |= GPIO_DIR_11_BITS_OUTPUT;
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int I2C_ReadBuffer(void *pBuffer, uint8_t Size)
|
||||
{
|
||||
uint8_t *pData = (uint8_t *)pBuffer;
|
||||
uint8_t i;
|
||||
|
||||
if (Size == 1) {
|
||||
*pData = I2C_Read(true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < Size - 1; i++) {
|
||||
SYSTICK_DelayUs(1);
|
||||
pData[i] = I2C_Read(false);
|
||||
}
|
||||
|
||||
SYSTICK_DelayUs(1);
|
||||
pData[i++] = I2C_Read(true);
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
||||
int I2C_WriteBuffer(const void *pBuffer, uint8_t Size)
|
||||
{
|
||||
const uint8_t *pData = (const uint8_t *)pBuffer;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < Size; i++) {
|
||||
if (I2C_Write(*pData++) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
38
driver/i2c.h
Normal file
38
driver/i2c.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_I2C_H
|
||||
#define DRIVER_I2C_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
I2C_WRITE = 0U,
|
||||
I2C_READ = 1U,
|
||||
};
|
||||
|
||||
void I2C_Start(void);
|
||||
void I2C_Stop(void);
|
||||
|
||||
uint8_t I2C_Read(bool bFinal);
|
||||
int I2C_Write(uint8_t Data);
|
||||
|
||||
int I2C_ReadBuffer(void *pBuffer, uint8_t Size);
|
||||
int I2C_WriteBuffer(const void *pBuffer, uint8_t Size);
|
||||
|
||||
#endif
|
||||
|
157
driver/keyboard.c
Normal file
157
driver/keyboard.c
Normal file
@ -0,0 +1,157 @@
|
||||
/* Copyright 2023 Manuel Jinger
|
||||
* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/keyboard.h"
|
||||
#include "driver/systick.h"
|
||||
|
||||
KEY_Code_t gKeyReading0 = KEY_INVALID;
|
||||
KEY_Code_t gKeyReading1 = KEY_INVALID;
|
||||
uint16_t gDebounceCounter;
|
||||
bool gWasFKeyPressed;
|
||||
|
||||
KEY_Code_t KEYBOARD_Poll(void)
|
||||
{
|
||||
KEY_Code_t Key = KEY_INVALID;
|
||||
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_5);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_7);
|
||||
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
// Keys connected to gnd
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0)) {
|
||||
Key = KEY_SIDE1;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1)) {
|
||||
Key = KEY_SIDE2;
|
||||
goto Bye;
|
||||
}
|
||||
// Original doesn't do PTT
|
||||
|
||||
// First row
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0)) {
|
||||
Key = KEY_MENU;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1)) {
|
||||
Key = KEY_1;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_2)) {
|
||||
Key = KEY_4;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_3)) {
|
||||
Key = KEY_7;
|
||||
goto Bye;
|
||||
}
|
||||
|
||||
// Second row
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_5);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0)) {
|
||||
Key = KEY_UP;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1)) {
|
||||
Key = KEY_2;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_2)) {
|
||||
Key = KEY_5;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_3)) {
|
||||
Key = KEY_8;
|
||||
goto Bye;
|
||||
}
|
||||
|
||||
// Third row
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_5);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0)) {
|
||||
Key = KEY_DOWN;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1)) {
|
||||
Key = KEY_3;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_2)) {
|
||||
Key = KEY_6;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_3)) {
|
||||
Key = KEY_9;
|
||||
goto Bye;
|
||||
}
|
||||
|
||||
// Fourth row
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_7);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0)) {
|
||||
Key = KEY_EXIT;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1)) {
|
||||
Key = KEY_STAR;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_2)) {
|
||||
Key = KEY_0;
|
||||
goto Bye;
|
||||
}
|
||||
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_3)) {
|
||||
Key = KEY_F;
|
||||
goto Bye;
|
||||
}
|
||||
|
||||
Bye:
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_5);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_7);
|
||||
|
||||
return Key;
|
||||
}
|
||||
|
57
driver/keyboard.h
Normal file
57
driver/keyboard.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* Copyright 2023 Manuel Jinger
|
||||
* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_KEYBOARD_H
|
||||
#define DRIVER_KEYBOARD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum KEY_Code_t {
|
||||
KEY_0 = 0,
|
||||
KEY_1 = 1,
|
||||
KEY_2 = 2,
|
||||
KEY_3 = 3,
|
||||
KEY_4 = 4,
|
||||
KEY_5 = 5,
|
||||
KEY_6 = 6,
|
||||
KEY_7 = 7,
|
||||
KEY_8 = 8,
|
||||
KEY_9 = 9,
|
||||
KEY_MENU = 10,
|
||||
KEY_UP = 11,
|
||||
KEY_DOWN = 12,
|
||||
KEY_EXIT = 13,
|
||||
KEY_STAR = 14,
|
||||
KEY_F = 15,
|
||||
KEY_PTT = 21,
|
||||
KEY_SIDE2 = 22,
|
||||
KEY_SIDE1 = 23,
|
||||
KEY_INVALID = 255,
|
||||
};
|
||||
|
||||
typedef enum KEY_Code_t KEY_Code_t;
|
||||
|
||||
extern KEY_Code_t gKeyReading0;
|
||||
extern KEY_Code_t gKeyReading1;
|
||||
extern uint16_t gDebounceCounter;
|
||||
extern bool gWasFKeyPressed;
|
||||
|
||||
KEY_Code_t KEYBOARD_Poll(void);
|
||||
|
||||
#endif
|
||||
|
116
driver/spi.c
Normal file
116
driver/spi.c
Normal file
@ -0,0 +1,116 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ARMCM0.h"
|
||||
#include "bsp/dp32g030/spi.h"
|
||||
#include "bsp/dp32g030/syscon.h"
|
||||
#include "bsp/dp32g030/irq.h"
|
||||
#include "driver/spi.h"
|
||||
|
||||
void SPI0_Init(void)
|
||||
{
|
||||
SPI_Config_t Config;
|
||||
|
||||
SPI_Disable(&SPI0->CR);
|
||||
|
||||
Config.TXFIFO_EMPTY = 0;
|
||||
Config.RXFIFO_HFULL = 0;
|
||||
Config.RXFIFO_FULL = 0;
|
||||
Config.RXFIFO_OVF = 0;
|
||||
Config.MSTR = 1;
|
||||
Config.SPR = 2;
|
||||
Config.CPHA = 1;
|
||||
Config.CPOL = 1;
|
||||
Config.LSB = 0;
|
||||
Config.TF_CLR = 0;
|
||||
Config.RF_CLR = 0;
|
||||
Config.TXFIFO_HFULL = 0;
|
||||
SPI_Configure(SPI0, &Config);
|
||||
|
||||
SPI_Enable(&SPI0->CR);
|
||||
}
|
||||
|
||||
void SPI_WaitForUndocumentedTxFifoStatusBit(void)
|
||||
{
|
||||
uint32_t Timeout;
|
||||
|
||||
Timeout = 0;
|
||||
do {
|
||||
// Undocumented bit!
|
||||
if ((SPI0->IF & 0x20) == 0) {
|
||||
break;
|
||||
}
|
||||
Timeout++;
|
||||
} while (Timeout <= 100000);
|
||||
}
|
||||
|
||||
void SPI_Disable(volatile uint32_t *pCR)
|
||||
{
|
||||
*pCR = (*pCR & ~SPI_CR_SPE_MASK) | SPI_CR_SPE_BITS_DISABLE;
|
||||
}
|
||||
|
||||
void SPI_Configure(volatile SPI_Port_t *pPort, SPI_Config_t *pConfig)
|
||||
{
|
||||
if (pPort == SPI0) {
|
||||
SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SPI0_MASK) | SYSCON_DEV_CLK_GATE_SPI0_BITS_ENABLE;
|
||||
} else if (pPort == SPI1) {
|
||||
SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SPI1_MASK) | SYSCON_DEV_CLK_GATE_SPI1_BITS_ENABLE;
|
||||
}
|
||||
|
||||
SPI_Disable(&pPort->CR);
|
||||
|
||||
pPort->CR = 0
|
||||
| (pPort->CR & ~(SPI_CR_SPR_MASK | SPI_CR_CPHA_MASK | SPI_CR_CPOL_MASK | SPI_CR_MSTR_MASK | SPI_CR_LSB_MASK | SPI_CR_RF_CLR_MASK))
|
||||
| ((pConfig->SPR << SPI_CR_SPR_SHIFT) & SPI_CR_SPR_MASK)
|
||||
| ((pConfig->CPHA << SPI_CR_CPHA_SHIFT) & SPI_CR_CPHA_MASK)
|
||||
| ((pConfig->CPOL << SPI_CR_CPOL_SHIFT) & SPI_CR_CPOL_MASK)
|
||||
| ((pConfig->MSTR << SPI_CR_MSTR_SHIFT) & SPI_CR_MSTR_MASK)
|
||||
| ((pConfig->LSB << SPI_CR_LSB_SHIFT) & SPI_CR_LSB_MASK)
|
||||
| ((pConfig->RF_CLR << SPI_CR_RF_CLR_SHIFT) & SPI_CR_RF_CLR_MASK)
|
||||
| ((pConfig->TF_CLR << SPI_CR_TF_CLR_SHIFT) & SPI_CR_TF_CLR_MASK)
|
||||
;
|
||||
|
||||
pPort->IE = 0
|
||||
| ((pConfig->RXFIFO_OVF << SPI_IE_RXFIFO_OVF_SHIFT) & SPI_IE_RXFIFO_OVF_MASK)
|
||||
| ((pConfig->RXFIFO_FULL << SPI_IE_RXFIFO_FULL_SHIFT) & SPI_IE_RXFIFO_FULL_MASK)
|
||||
| ((pConfig->RXFIFO_HFULL << SPI_IE_RXFIFO_HFULL_SHIFT) & SPI_IE_RXFIFO_HFULL_MASK)
|
||||
| ((pConfig->TXFIFO_EMPTY << SPI_IE_TXFIFO_EMPTY_SHIFT) & SPI_IE_TXFIFO_EMPTY_MASK)
|
||||
| ((pConfig->TXFIFO_HFULL << SPI_IE_TXFIFO_HFULL_SHIFT) & SPI_IE_TXFIFO_HFULL_MASK)
|
||||
;
|
||||
|
||||
if (pPort->IE) {
|
||||
if (pPort == SPI0) {
|
||||
NVIC_EnableIRQ(DP32_SPI0_IRQn);
|
||||
} else if (pPort == SPI1) {
|
||||
NVIC_EnableIRQ(DP32_SPI1_IRQn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPI_ToggleMasterMode(volatile uint32_t *pCR, bool bIsMaster)
|
||||
{
|
||||
if (bIsMaster) {
|
||||
*pCR = (*pCR & ~SPI_CR_MSR_SSN_MASK) | SPI_CR_MSR_SSN_BITS_ENABLE;
|
||||
} else {
|
||||
*pCR = (*pCR & ~SPI_CR_MSR_SSN_MASK) | SPI_CR_MSR_SSN_BITS_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void SPI_Enable(volatile uint32_t *pCR)
|
||||
{
|
||||
*pCR = (*pCR & ~SPI_CR_SPE_MASK) | SPI_CR_SPE_BITS_ENABLE;
|
||||
}
|
||||
|
47
driver/spi.h
Normal file
47
driver/spi.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_SPI_H
|
||||
#define DRIVER_SPI_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t MSTR;
|
||||
uint8_t SPR;
|
||||
uint8_t CPHA;
|
||||
uint8_t CPOL;
|
||||
uint8_t LSB;
|
||||
uint8_t TF_CLR;
|
||||
uint8_t RF_CLR;
|
||||
uint8_t TXFIFO_HFULL;
|
||||
uint8_t TXFIFO_EMPTY;
|
||||
uint8_t RXFIFO_HFULL;
|
||||
uint8_t RXFIFO_FULL;
|
||||
uint8_t RXFIFO_OVF;
|
||||
} SPI_Config_t;
|
||||
|
||||
void SPI0_Init(void);
|
||||
void SPI_WaitForUndocumentedTxFifoStatusBit(void);
|
||||
|
||||
void SPI_Disable(volatile uint32_t *pCR);
|
||||
void SPI_Configure(volatile SPI_Port_t *pPort, SPI_Config_t *pConfig);
|
||||
void SPI_ToggleMasterMode(volatile uint32_t *pCr, bool bIsMaster);
|
||||
void SPI_Enable(volatile uint32_t *pCR);
|
||||
|
||||
#endif
|
||||
|
176
driver/st7565.c
Normal file
176
driver/st7565.c
Normal file
@ -0,0 +1,176 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bsp/dp32g030/spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi.h"
|
||||
#include "driver/st7565.h"
|
||||
#include "driver/system.h"
|
||||
|
||||
uint8_t gStatusLine[128];
|
||||
uint8_t gFrameBuffer[7][128];
|
||||
|
||||
void ST7565_DrawLine(uint8_t Column, uint8_t Line, uint16_t Size, const uint8_t *pBitmap, bool bIsClearMode)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
ST7565_SelectColumnAndLine(Column + 4U, Line);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
|
||||
if (!bIsClearMode) {
|
||||
for (i = 0; i < Size; i++) {
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = pBitmap[i];
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < Size; i++) {
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_BlitFullScreen(void)
|
||||
{
|
||||
uint8_t Line;
|
||||
uint8_t Column;
|
||||
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
ST7565_WriteByte(0x40);
|
||||
|
||||
for (Line = 0; Line < 7; Line++) {
|
||||
ST7565_SelectColumnAndLine(4U, Line + 1U);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
for (Column = 0; Column < 128; Column++) {
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = gFrameBuffer[Line][Column];
|
||||
}
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
}
|
||||
|
||||
SYSTEM_DelayMs(20);
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_BlitStatusLine(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
ST7565_WriteByte(0x40);
|
||||
ST7565_SelectColumnAndLine(4, 0);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
|
||||
for (i = 0; i < 0x80; i++) {
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = gStatusLine[i];
|
||||
}
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_FillScreen(uint8_t Value)
|
||||
{
|
||||
uint8_t i, j;
|
||||
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
for (i = 0; i < 8; i++) {
|
||||
ST7565_SelectColumnAndLine(0, i);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
for (j = 0; j < 132; j++) {
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = Value;
|
||||
}
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
}
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_Init(void)
|
||||
{
|
||||
SPI0_Init();
|
||||
ST7565_Configure_GPIO_B11();
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
ST7565_WriteByte(0xE2);
|
||||
SYSTEM_DelayMs(0x78);
|
||||
ST7565_WriteByte(0xA2);
|
||||
ST7565_WriteByte(0xC0);
|
||||
ST7565_WriteByte(0xA1);
|
||||
ST7565_WriteByte(0xA6);
|
||||
ST7565_WriteByte(0xA4);
|
||||
ST7565_WriteByte(0x24);
|
||||
ST7565_WriteByte(0x81);
|
||||
ST7565_WriteByte(0x1F);
|
||||
ST7565_WriteByte(0x2B);
|
||||
SYSTEM_DelayMs(1);
|
||||
ST7565_WriteByte(0x2E);
|
||||
SYSTEM_DelayMs(1);
|
||||
ST7565_WriteByte(0x2F);
|
||||
ST7565_WriteByte(0x2F);
|
||||
ST7565_WriteByte(0x2F);
|
||||
ST7565_WriteByte(0x2F);
|
||||
SYSTEM_DelayMs(0x28);
|
||||
ST7565_WriteByte(0x40);
|
||||
ST7565_WriteByte(0xAF);
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
ST7565_FillScreen(0x00);
|
||||
}
|
||||
|
||||
void ST7565_Configure_GPIO_B11(void)
|
||||
{
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES);
|
||||
SYSTEM_DelayMs(1);
|
||||
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES);
|
||||
SYSTEM_DelayMs(20);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES);
|
||||
SYSTEM_DelayMs(120);
|
||||
}
|
||||
|
||||
void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line)
|
||||
{
|
||||
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = Line + 0xB0;
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = ((Column >> 4) & 0x0F) | 0x10;
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = ((Column >> 0) & 0x0F);
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
}
|
||||
|
||||
void ST7565_WriteByte(uint8_t Value)
|
||||
{
|
||||
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {
|
||||
}
|
||||
SPI0->WDR = Value;
|
||||
}
|
||||
|
36
driver/st7565.h
Normal file
36
driver/st7565.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_ST7565_H
|
||||
#define DRIVER_ST7565_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint8_t gStatusLine[128];
|
||||
extern uint8_t gFrameBuffer[7][128];
|
||||
|
||||
void ST7565_DrawLine(uint8_t Column, uint8_t Line, uint16_t Size, const uint8_t *pBitmap, bool bIsClearMode);
|
||||
void ST7565_BlitFullScreen(void);
|
||||
void ST7565_BlitStatusLine(void);
|
||||
void ST7565_FillScreen(uint8_t Value);
|
||||
void ST7565_Init(void);
|
||||
void ST7565_Configure_GPIO_B11(void);
|
||||
void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line);
|
||||
void ST7565_WriteByte(uint8_t Value);
|
||||
|
||||
#endif
|
||||
|
40
driver/system.c
Normal file
40
driver/system.c
Normal file
@ -0,0 +1,40 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bsp/dp32g030/pmu.h"
|
||||
#include "bsp/dp32g030/syscon.h"
|
||||
#include "driver/system.h"
|
||||
#include "driver/systick.h"
|
||||
|
||||
void SYSTEM_DelayMs(uint32_t Delay)
|
||||
{
|
||||
SYSTICK_DelayUs(Delay * 1000);
|
||||
}
|
||||
|
||||
void SYSTEM_ConfigureClocks(void)
|
||||
{
|
||||
// Set source clock from external crystal
|
||||
PMU_SRC_CFG = (PMU_SRC_CFG & ~(PMU_SRC_CFG_RCHF_SEL_MASK | PMU_SRC_CFG_RCHF_EN_MASK))
|
||||
| PMU_SRC_CFG_RCHF_SEL_BITS_48MHZ
|
||||
| PMU_SRC_CFG_RCHF_EN_BITS_ENABLE;
|
||||
|
||||
// Divide by 2
|
||||
SYSCON_CLK_SEL = SYSCON_CLK_SEL_DIV_BITS_2;
|
||||
|
||||
// Disable division clock gate
|
||||
SYSCON_DIV_CLK_GATE = (SYSCON_DIV_CLK_GATE & ~SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_MASK) | SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_BITS_DISABLE;
|
||||
}
|
||||
|
26
driver/system.h
Normal file
26
driver/system.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_SYSTEM_H
|
||||
#define DRIVER_SYSTEM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void SYSTEM_DelayMs(uint32_t Delay);
|
||||
void SYSTEM_ConfigureClocks(void);
|
||||
|
||||
#endif
|
||||
|
54
driver/systick.c
Normal file
54
driver/systick.c
Normal file
@ -0,0 +1,54 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ARMCM0.h"
|
||||
#include "driver/systick.h"
|
||||
#include "misc.h"
|
||||
|
||||
// 0x20000324
|
||||
static uint32_t gTickMultiplier;
|
||||
|
||||
void SYSTICK_Init(void)
|
||||
{
|
||||
SysTick_Config(480000);
|
||||
gTickMultiplier = 48;
|
||||
}
|
||||
|
||||
void SYSTICK_DelayUs(uint32_t Delay)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t Start;
|
||||
uint32_t Previous;
|
||||
uint32_t Current;
|
||||
uint32_t Delta;
|
||||
|
||||
i = 0;
|
||||
Start = SysTick->LOAD;
|
||||
Previous = SysTick->VAL;
|
||||
do {
|
||||
do {
|
||||
Current = SysTick->VAL;
|
||||
} while (Current == Previous);
|
||||
if (Current < Previous) {
|
||||
Delta = -Current;
|
||||
} else {
|
||||
Delta = Start - Current;
|
||||
}
|
||||
i += Delta + Previous;
|
||||
Previous = Current;
|
||||
} while (i < Delay * gTickMultiplier);
|
||||
}
|
||||
|
26
driver/systick.h
Normal file
26
driver/systick.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_SYSTICK_H
|
||||
#define DRIVER_SYSTICK_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void SYSTICK_Init(void);
|
||||
void SYSTICK_DelayUs(uint32_t Delay);
|
||||
|
||||
#endif
|
||||
|
104
driver/uart.c
Normal file
104
driver/uart.c
Normal file
@ -0,0 +1,104 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "bsp/dp32g030/dma.h"
|
||||
#include "bsp/dp32g030/syscon.h"
|
||||
#include "bsp/dp32g030/uart.h"
|
||||
#include "driver/uart.h"
|
||||
|
||||
static bool UART_IsLogEnabled;
|
||||
uint8_t UART_DMA_Buffer[256];
|
||||
|
||||
void UART_Init(void)
|
||||
{
|
||||
uint32_t Delta;
|
||||
uint32_t Positive;
|
||||
uint32_t Frequency;
|
||||
|
||||
UART1->CTRL = (UART1->CTRL & ~UART_CTRL_UARTEN_MASK) | UART_CTRL_UARTEN_BITS_DISABLE;
|
||||
Delta = SYSCON_RC_FREQ_DELTA;
|
||||
Positive = (Delta & SYSCON_RC_FREQ_DELTA_RCHF_SIG_MASK) >> SYSCON_RC_FREQ_DELTA_RCHF_SIG_SHIFT;
|
||||
Frequency = (Delta & SYSCON_RC_FREQ_DELTA_RCHF_DELTA_MASK) >> SYSCON_RC_FREQ_DELTA_RCHF_DELTA_SHIFT;
|
||||
if (Positive) {
|
||||
Frequency += 48000000U;
|
||||
} else {
|
||||
Frequency = 48000000U - Frequency;
|
||||
}
|
||||
|
||||
UART1->BAUD = Frequency / 39053U;
|
||||
UART1->CTRL = UART_CTRL_RXEN_BITS_ENABLE | UART_CTRL_TXEN_BITS_ENABLE | UART_CTRL_RXDMAEN_BITS_ENABLE;
|
||||
UART1->RXTO = 4;
|
||||
UART1->FC = 0;
|
||||
UART1->FIFO = UART_FIFO_RF_LEVEL_BITS_8_BYTE | UART_FIFO_RF_CLR_BITS_ENABLE | UART_FIFO_TF_CLR_BITS_ENABLE;
|
||||
UART1->IE = 0;
|
||||
|
||||
DMA_CTR = (DMA_CTR & ~DMA_CTR_DMAEN_MASK) | DMA_CTR_DMAEN_BITS_DISABLE;
|
||||
|
||||
DMA_CH0->MSADDR = (uint32_t)(uintptr_t)&UART1->RDR;
|
||||
DMA_CH0->MDADDR = (uint32_t)(uintptr_t)UART_DMA_Buffer;
|
||||
DMA_CH0->MOD = 0
|
||||
// Source
|
||||
| DMA_CH_MOD_MS_ADDMOD_BITS_NONE
|
||||
| DMA_CH_MOD_MS_SIZE_BITS_8BIT
|
||||
| DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS1
|
||||
// Destination
|
||||
| DMA_CH_MOD_MD_ADDMOD_BITS_INCREMENT
|
||||
| DMA_CH_MOD_MD_SIZE_BITS_8BIT
|
||||
| DMA_CH_MOD_MD_SEL_BITS_SRAM
|
||||
;
|
||||
DMA_INTEN = 0;
|
||||
DMA_INTST = 0
|
||||
| DMA_INTST_CH0_TC_INTST_BITS_SET
|
||||
| DMA_INTST_CH1_TC_INTST_BITS_SET
|
||||
| DMA_INTST_CH2_TC_INTST_BITS_SET
|
||||
| DMA_INTST_CH3_TC_INTST_BITS_SET
|
||||
| DMA_INTST_CH0_THC_INTST_BITS_SET
|
||||
| DMA_INTST_CH1_THC_INTST_BITS_SET
|
||||
| DMA_INTST_CH2_THC_INTST_BITS_SET
|
||||
| DMA_INTST_CH3_THC_INTST_BITS_SET
|
||||
;
|
||||
DMA_CH0->CTR = 0
|
||||
| DMA_CH_CTR_CH_EN_BITS_ENABLE
|
||||
| ((0xFF << DMA_CH_CTR_LENGTH_SHIFT) & DMA_CH_CTR_LENGTH_MASK)
|
||||
| DMA_CH_CTR_LOOP_BITS_ENABLE
|
||||
| DMA_CH_CTR_PRI_BITS_MEDIUM
|
||||
;
|
||||
UART1->IF = UART_IF_RXTO_BITS_SET;
|
||||
|
||||
DMA_CTR = (DMA_CTR & ~DMA_CTR_DMAEN_MASK) | DMA_CTR_DMAEN_BITS_ENABLE;
|
||||
|
||||
UART1->CTRL |= UART_CTRL_UARTEN_BITS_ENABLE;
|
||||
}
|
||||
|
||||
void UART_Send(const void *pBuffer, uint32_t Size)
|
||||
{
|
||||
const uint8_t *pData = (const uint8_t *)pBuffer;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < Size; i++) {
|
||||
UART1->TDR = pData[i];
|
||||
while ((UART1->IF & UART_IF_TXFIFO_FULL_MASK) != UART_IF_TXFIFO_FULL_BITS_NOT_SET) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UART_LogSend(const void *pBuffer, uint32_t Size)
|
||||
{
|
||||
if (UART_IsLogEnabled) {
|
||||
UART_Send(pBuffer, Size);
|
||||
}
|
||||
}
|
30
driver/uart.h
Normal file
30
driver/uart.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_UART_H
|
||||
#define DRIVER_UART_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint8_t UART_DMA_Buffer[256];
|
||||
|
||||
void UART_Init(void);
|
||||
void UART_Send(const void *pBuffer, uint32_t Size);
|
||||
void UART_LogSend(const void *pBuffer, uint32_t Size);
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user