add ui, change project struct

This commit is contained in:
Sheikah
2023-01-23 16:39:02 +08:00
parent 5f59f9412a
commit df4db6d8c4
150 changed files with 931 additions and 741 deletions

View File

@ -0,0 +1,26 @@
#include "RotaryCoder.h"
uint16_t COUNT;
uint16_t DIR;
uint8_t EC11_init(void)
{
COUNT = 0;
DIR = 0;
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
// HAL_TIM_Encoder_Start_IT(&htim3,TIM_CHANNEL_ALL);
return 1;
}
uint16_t EC11_DIR(void)
{
DIR = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);
// STATUS.DATA.COUNT = __HAL_TIM_GET_COUNTER(&htim3);
return DIR;
}
uint16_t EC11_COUNT(void)
{
COUNT = __HAL_TIM_GET_COUNTER(&htim3);
return COUNT;
}

View File

@ -0,0 +1,13 @@
// Rotary encoder library for Arduino.
#include "hardware.h"
#include "tim.h"
#ifndef rotary_h
#define rotary_h
uint8_t
EC11_init(void);
// Process pin(s)
uint16_t EC11_DIR(void);
uint16_t EC11_COUNT(void);
#endif

View File

@ -0,0 +1,286 @@
/* vim: set ai et ts=4 sw=4: */
#include <stdint.h>
#include "gpio.h"
#include "spi.h"
#include "st7735.h"
#define DELAY 0x80
// based on Adafruit ST7735 library for Arduino
static const uint8_t
init_cmds1[] = { // Init for 7735R, part 1 (red or green tab)
15, // 15 commands in list:
ST7735_SWRESET, DELAY, // 1: Software reset, 0 args, w/delay
150, // 150 ms delay
ST7735_SLPOUT, DELAY, // 2: Out of sleep mode, 0 args, w/delay
255, // 500 ms delay
ST7735_FRMCTR1, 3, // 3: Frame rate ctrl - normal mode, 3 args:
0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D)
ST7735_FRMCTR2, 3, // 4: Frame rate control - idle mode, 3 args:
0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D)
ST7735_FRMCTR3, 6, // 5: Frame rate ctrl - partial mode, 6 args:
0x01, 0x2C, 0x2D, // Dot inversion mode
0x01, 0x2C, 0x2D, // Line inversion mode
ST7735_INVCTR, 1, // 6: Display inversion ctrl, 1 arg, no delay:
0x07, // No inversion
ST7735_PWCTR1, 3, // 7: Power control, 3 args, no delay:
0xA2,
0x02, // -4.6V
0x84, // AUTO mode
ST7735_PWCTR2, 1, // 8: Power control, 1 arg, no delay:
0xC5, // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
ST7735_PWCTR3, 2, // 9: Power control, 2 args, no delay:
0x0A, // Opamp current small
0x00, // Boost frequency
ST7735_PWCTR4, 2, // 10: Power control, 2 args, no delay:
0x8A, // BCLK/2, Opamp current small & Medium low
0x2A,
ST7735_PWCTR5, 2, // 11: Power control, 2 args, no delay:
0x8A, 0xEE,
ST7735_VMCTR1, 1, // 12: Power control, 1 arg, no delay:
0x0E,
ST7735_INVOFF, 0, // 13: Don't invert display, no args, no delay
ST7735_MADCTL, 1, // 14: Memory access control (directions), 1 arg:
ST7735_ROTATION, // row addr/col addr, bottom to top refresh
ST7735_COLMOD, 1, // 15: set color mode, 1 arg, no delay:
0x05}, // 16-bit color
#if (defined(ST7735_IS_128X128) || defined(ST7735_IS_160X128))
init_cmds2[] = { // Init for 7735R, part 2 (1.44" display)
2, // 2 commands in list:
ST7735_CASET, 4, // 1: Column addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x7F, // XEND = 127
ST7735_RASET, 4, // 2: Row addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x7F}, // XEND = 127
#endif // ST7735_IS_128X128
#ifdef ST7735_IS_160X80
init_cmds2[] = { // Init for 7735S, part 2 (160x80 display)
3, // 3 commands in list:
ST7735_CASET, 4, // 1: Column addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x4F, // XEND = 79
ST7735_RASET, 4, // 2: Row addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x9F, // XEND = 159
ST7735_INVOFF, 0}, // 3: Invert colors
#endif
init_cmds3[] = { // Init for 7735R, part 3 (red or green tab)
4, // 4 commands in list:
ST7735_GMCTRP1, 16, // 1: Magical unicorn dust, 16 args, no delay:
0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, ST7735_GMCTRN1, 16, // 2: Sparkles and rainbows, 16 args, no delay:
0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, ST7735_NORON, DELAY, // 3: Normal display on, no args, w/delay
10, // 10 ms delay
ST7735_DISPON, DELAY, // 4: Main screen turn on, no args w/delay
100}; // 100 ms delay
static void ST7735_Select()
{
HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_RESET);
}
void ST7735_Unselect()
{
HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_SET);
}
static void ST7735_Reset()
{
HAL_GPIO_WritePin(ST7735_RES_GPIO_Port, ST7735_RES_Pin, GPIO_PIN_RESET);
HAL_Delay(5);
HAL_GPIO_WritePin(ST7735_RES_GPIO_Port, ST7735_RES_Pin, GPIO_PIN_SET);
}
static void ST7735_WriteCommand(uint8_t cmd)
{
HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(&ST7735_SPI_PORT, &cmd, sizeof(cmd), HAL_MAX_DELAY);
// SPI_Write(&cmd, sizeof(cmd));
}
static void ST7735_WriteData(uint8_t *buff, size_t buff_size)
{
HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET);
HAL_SPI_Transmit(&ST7735_SPI_PORT, buff, buff_size, HAL_MAX_DELAY);
// SPI_Write(buff, buff_size);
}
static void ST7735_ExecuteCommandList(const uint8_t *addr)
{
uint8_t numCommands, numArgs;
uint16_t ms;
numCommands = *addr++;
while (numCommands--)
{
uint8_t cmd = *addr++;
ST7735_WriteCommand(cmd);
numArgs = *addr++;
// If high bit set, delay follows args
ms = numArgs & DELAY;
numArgs &= ~DELAY;
if (numArgs)
{
ST7735_WriteData((uint8_t *)addr, numArgs);
addr += numArgs;
}
if (ms)
{
ms = *addr++;
if (ms == 255)
ms = 500;
HAL_Delay(ms);
}
}
}
static void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
{
// column address set
ST7735_WriteCommand(ST7735_CASET);
uint8_t data[] = {0x00, x0 + ST7735_XSTART, 0x00, x1 + ST7735_XSTART};
ST7735_WriteData(data, sizeof(data));
// row address set
ST7735_WriteCommand(ST7735_RASET);
data[1] = y0 + ST7735_YSTART;
data[3] = y1 + ST7735_YSTART;
ST7735_WriteData(data, sizeof(data));
}
void ST7735_Init()
{
ST7735_Select();
ST7735_Reset();
ST7735_ExecuteCommandList(init_cmds1);
ST7735_ExecuteCommandList(init_cmds2);
ST7735_ExecuteCommandList(init_cmds3);
ST7735_Unselect();
}
void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color) //画点
{
if ((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT))
return;
ST7735_Select();
ST7735_SetAddressWindow(x, y, x + 1, y + 1);
ST7735_WriteCommand(ST7735_RAMWR);
uint8_t data[] = {color >> 8, color & 0xFF};
ST7735_WriteData(data, sizeof(data));
ST7735_Unselect();
}
void ST7735_DrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,uint16_t color) //画线
{
int16_t temp;
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
temp = x0;
x0 = y0;
y0 = temp;
temp = x1;
x0 = y1;
y1 = temp;
}
if (x0 > x1) {
temp = x1;
x1 = x0;
x0 = temp;
temp = y1;
y1 = y0;
y0 = temp;
}
int16_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int16_t err = dx / 2;
int16_t ystep;
if (y0 < y1) {
ystep = 1;
} else {
ystep = -1;
}
for (; x0 <= x1; x0++) {
if (steep) {
ST7735_DrawPixel(y0, x0, color);
} else {
ST7735_DrawPixel(x0, y0, color);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
void ST7735_FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) //矩形填充
{
// clipping
if ((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT))
return;
if ((x + w - 1) >= ST7735_WIDTH)
w = ST7735_WIDTH - x;
if ((y + h - 1) >= ST7735_HEIGHT)
h = ST7735_HEIGHT - y;
ST7735_Select();
ST7735_SetAddressWindow(x, y, x + w - 1, y + h - 1);
ST7735_WriteCommand(ST7735_RAMWR);
uint8_t data[] = {color >> 8, color & 0xFF};
HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET);
for (y = h; y > 0; y--)
{
for (x = w; x > 0; x--)
{
HAL_SPI_Transmit(&ST7735_SPI_PORT, data, sizeof(data), HAL_MAX_DELAY);
// SPI_Write(data, sizeof(data));
}
}
ST7735_Unselect();
}
void ST7735_FillScreen(uint16_t color) //全屏填充
{
ST7735_FillRectangle(0, 0, ST7735_WIDTH, ST7735_HEIGHT, color);
}
void ST7735_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t *data) //画图像
{
if ((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT))
return;
if ((x + w - 1) >= ST7735_WIDTH)
return;
if ((y + h - 1) >= ST7735_HEIGHT)
return;
ST7735_Select();
ST7735_SetAddressWindow(x, y, x + w - 1, y + h - 1);
ST7735_WriteCommand(ST7735_RAMWR);
ST7735_WriteData((uint8_t *)data, sizeof(uint16_t) * w * h);
ST7735_Unselect();
}
void ST7735_InvertColors(bool invert) //反转颜色
{
ST7735_Select();
ST7735_WriteCommand(invert ? ST7735_INVON : ST7735_INVOFF);
ST7735_Unselect();
}

View File

@ -0,0 +1,249 @@
/* vim: set ai et ts=4 sw=4: */
#ifndef __ST7735_H__
#define __ST7735_H__
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "spi.h"
#define ST7735_MADCTL_MY 0x80
#define ST7735_MADCTL_MX 0x40
#define ST7735_MADCTL_MV 0x20
#define ST7735_MADCTL_ML 0x10
#define ST7735_MADCTL_RGB 0x00
#define ST7735_MADCTL_BGR 0x08
#define ST7735_MADCTL_MH 0x04
/*** Redefine if necessary ***/
#define ST7735_SPI_PORT hspi1 //<SPI_PORT>
extern SPI_HandleTypeDef ST7735_SPI_PORT;
#define ST7735_RES_Pin LCD_RST_Pin
#define ST7735_RES_GPIO_Port LCD_RST_GPIO_Port
#define ST7735_DC_Pin LCD_DC_Pin
#define ST7735_DC_GPIO_Port LCD_DC_GPIO_Port
#define ST7735_CS_Pin GPIO_PIN_15
#define ST7735_CS_GPIO_Port GPIOA
/* // AliExpress/eBay 1.8" display, default orientation
#define ST7735_IS_160X128 1
#define ST7735_WIDTH 128
#define ST7735_HEIGHT 160
#define ST7735_XSTART 0
#define ST7735_YSTART 0
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY)
*/
// AliExpress/eBay 1.8" display, rotate right
/*
#define ST7735_IS_160X128 1
#define ST7735_WIDTH 160
#define ST7735_HEIGHT 128
#define ST7735_XSTART 0
#define ST7735_YSTART 0
#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV)
*/
// AliExpress/eBay 1.8" display, rotate left
/*
#define ST7735_IS_160X128 1
#define ST7735_WIDTH 160
#define ST7735_HEIGHT 128
#define ST7735_XSTART 0
#define ST7735_YSTART 0
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV)
*/
// AliExpress/eBay 1.8" display, upside down
/*
#define ST7735_IS_160X128 1
#define ST7735_WIDTH 128
#define ST7735_HEIGHT 160
#define ST7735_XSTART 0
#define ST7735_YSTART 0
#define ST7735_ROTATION (0)
*/
// WaveShare ST7735S-based 1.8" display, default orientation
/*
#define ST7735_IS_160X128 1
#define ST7735_WIDTH 128
#define ST7735_HEIGHT 160
#define ST7735_XSTART 2
#define ST7735_YSTART 1
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_RGB)
*/
// WaveShare ST7735S-based 1.8" display, rotate right
/*
#define ST7735_IS_160X128 1
#define ST7735_WIDTH 160
#define ST7735_HEIGHT 128
#define ST7735_XSTART 1
#define ST7735_YSTART 2
#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_RGB)
*/
// WaveShare ST7735S-based 1.8" display, rotate left
#define ST7735_IS_160X128 1
#define ST7735_WIDTH 160
#define ST7735_HEIGHT 128
#define ST7735_XSTART 1
#define ST7735_YSTART 2
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_RGB)
// WaveShare ST7735S-based 1.8" display, upside down
/*
#define ST7735_IS_160X128 1
#define ST7735_WIDTH 128
#define ST7735_HEIGHT 160
#define ST7735_XSTART 2
#define ST7735_YSTART 1
#define ST7735_ROTATION (ST7735_MADCTL_RGB)
*/
/* // 1.44" display, default orientation
#define ST7735_IS_128X128 1
#define ST7735_WIDTH 128
#define ST7735_HEIGHT 128
#define ST7735_XSTART 2
#define ST7735_YSTART 3
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_BGR)
*/
// 1.44" display, rotate right
/*
#define ST7735_IS_128X128 1
#define ST7735_WIDTH 128
#define ST7735_HEIGHT 128
#define ST7735_XSTART 3
#define ST7735_YSTART 2
#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
*/
// 1.44" display, rotate left
/*
#define ST7735_IS_128X128 1
#define ST7735_WIDTH 128
#define ST7735_HEIGHT 128
#define ST7735_XSTART 1
#define ST7735_YSTART 2
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
*/
// 1.44" display, upside down
/*
#define ST7735_IS_128X128 1
#define ST7735_WIDTH 128
#define ST7735_HEIGHT 128
#define ST7735_XSTART 2
#define ST7735_YSTART 1
#define ST7735_ROTATION (ST7735_MADCTL_BGR)
*/
// mini 160x80 display (it's unlikely you want the default orientation)
/*
#define ST7735_IS_160X80 1
#define ST7735_XSTART 26
#define ST7735_YSTART 1
#define ST7735_WIDTH 80
#define ST7735_HEIGHT 160
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_BGR)
*/
// mini 160x80, rotate left
/*
#define ST7735_IS_160X80 1
#define ST7735_XSTART 1
#define ST7735_YSTART 26
#define ST7735_WIDTH 160
#define ST7735_HEIGHT 80
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
*/
// mini 160x80, rotate right
/*
#define ST7735_IS_160X80 1
#define ST7735_XSTART 0
#define ST7735_YSTART 24
#define ST7735_WIDTH 160
#define ST7735_HEIGHT 80
#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
*/
/****************************/
#define ST7735_NOP 0x00
#define ST7735_SWRESET 0x01
#define ST7735_RDDID 0x04
#define ST7735_RDDST 0x09
#define ST7735_SLPIN 0x10
#define ST7735_SLPOUT 0x11
#define ST7735_PTLON 0x12
#define ST7735_NORON 0x13
#define ST7735_INVOFF 0x20
#define ST7735_INVON 0x21
#define ST7735_DISPOFF 0x28
#define ST7735_DISPON 0x29
#define ST7735_CASET 0x2A
#define ST7735_RASET 0x2B
#define ST7735_RAMWR 0x2C
#define ST7735_RAMRD 0x2E
#define ST7735_PTLAR 0x30
#define ST7735_COLMOD 0x3A
#define ST7735_MADCTL 0x36
#define ST7735_FRMCTR1 0xB1
#define ST7735_FRMCTR2 0xB2
#define ST7735_FRMCTR3 0xB3
#define ST7735_INVCTR 0xB4
#define ST7735_DISSET5 0xB6
#define ST7735_PWCTR1 0xC0
#define ST7735_PWCTR2 0xC1
#define ST7735_PWCTR3 0xC2
#define ST7735_PWCTR4 0xC3
#define ST7735_PWCTR5 0xC4
#define ST7735_VMCTR1 0xC5
#define ST7735_RDID1 0xDA
#define ST7735_RDID2 0xDB
#define ST7735_RDID3 0xDC
#define ST7735_RDID4 0xDD
#define ST7735_PWCTR6 0xFC
#define ST7735_GMCTRP1 0xE0
#define ST7735_GMCTRN1 0xE1
// Color definitions
#define ST7735_BLACK 0x0000
#define ST7735_BLUE 0x001F
#define ST7735_RED 0xF800
#define ST7735_GREEN 0x07E0
#define ST7735_CYAN 0x07FF
#define ST7735_MAGENTA 0xF81F
#define ST7735_YELLOW 0xFFE0
#define ST7735_WHITE 0xFFFF
#define ST7735_COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
// call before initializing any SPI devices
void ST7735_Unselect(void);
void ST7735_Init(void);
void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color);
void ST7735_DrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,uint16_t color);
void ST7735_FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
void ST7735_FillScreen(uint16_t color);
void ST7735_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data);
void ST7735_InvertColors(bool invert);
#endif // __ST7735_H__

View File

@ -0,0 +1,764 @@
#include "i2c_sw.h"
#define SW_I2C_WAIT_TIME 22
#define I2C_READ 0x01
#define READ_CMD 1
#define WRITE_CMD 0
#define SW_I2C1_SCL_GPIO GPIO_SW_I2C1_SCL
#define SW_I2C1_SDA_GPIO GPIO_SW_I2C1_SDA
#define SW_I2C1_SCL_PIN GPIO_SW_I2C1_SCL_PIN
#define SW_I2C1_SDA_PIN GPIO_SW_I2C1_SDA_PIN
/*
#define SW_I2Cx_SCL_GPIO GPIO_SW_I2Cx_SCL
#define SW_I2Cx_SDA_GPIO GPIO_SW_I2Cx_SDA
#define SW_I2Cx_SCL_PIN GPIO_SW_I2Cx_SCL_PIN
#define SW_I2Cx_SDA_PIN GPIO_SW_I2Cx_SDA_PIN
*/
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
void TIMER__Wait_us(__IO uint32_t nCount)
{
for (; nCount != 0;nCount--);
}
/* //Systick功能实现us延时参数SYSCLK为系统时钟
#define AHB_INPUT 64 //请按RCC中设置的AHB时钟频率填写到这里单位MHz
void TIMER__Wait_us(__IO uint32_t uS) //uS微秒级延时程序参考值即是延时数72MHz时最大值233015
{
uint32_t temp;
SysTick->LOAD=AHB_INPUT*uS; //重装计数初值当主频是72MHz72次为1微秒
SysTick->VAL=0x00; //清空定时器的计数器
SysTick->CTRL=0x00000005; //内部时钟FCLK打开定时器
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL=0x00000004; //关闭定时器
SysTick->VAL=0x00; //清空定时器的计数器
} */
void SW_I2C_initial(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pin = GPIO_SW_I2C1_SCL_PIN;
HAL_GPIO_Init(GPIO_SW_I2C1_SCL, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_SW_I2C1_SDA_PIN;
HAL_GPIO_Init(GPIO_SW_I2C1_SDA, &GPIO_InitStructure);
/*
GPIO_InitStructure.Pin = GPIO_SW_I2Cx_SCL_PIN;
HAL_GPIO_Init(GPIO_SW_I2Cx_SCL, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_SW_I2Cx_SDA_PIN;
HAL_GPIO_Init(GPIO_SW_I2Cx_SDA, &GPIO_InitStructure);
*/
}
void GPIO_SetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
HAL_GPIO_WritePin(GPIOx,GPIO_Pin,GPIO_PIN_SET);
}
void GPIO_ResetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
HAL_GPIO_WritePin(GPIOx,GPIO_Pin,GPIO_PIN_RESET);
}
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
uint8_t Ret;
Ret=(uint16_t)HAL_GPIO_ReadPin(GPIOx,GPIO_Pin);
return Ret;
}
void sda_high(uint8_t sel)
{
if(sel == 1)
GPIO_SetBits(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN);
//else if(sel==x) ...
}
void sda_low(uint8_t sel)
{
if(sel == 1)
GPIO_ResetBits(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN);
//else if(sel==x) ...
}
void scl_high(uint8_t sel)
{
if(sel == 1)
GPIO_SetBits(SW_I2C1_SCL_GPIO, SW_I2C1_SCL_PIN);
//else if(sel==x) ...
}
void scl_low(uint8_t sel)
{
if(sel == 1)
GPIO_ResetBits(SW_I2C1_SCL_GPIO, SW_I2C1_SCL_PIN);
//else if(sel==x) ...
}
void sda_out(uint8_t sel, uint8_t out)
{
if (out)
{
sda_high(sel);
}
else
{
sda_low(sel);
}
}
void sda_in_mode(uint8_t sel)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Mode=GPIO_MODE_INPUT;
if(sel == 1)
{
GPIO_InitStructure.Pin = SW_I2C1_SDA_PIN;
HAL_GPIO_Init(SW_I2C1_SDA_GPIO, &GPIO_InitStructure);
}
//else if(sel==x) ...
}
void sda_out_mode(uint8_t sel)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_OD;
if(sel == 1)
{
GPIO_InitStructure.Pin = SW_I2C1_SDA_PIN;
HAL_GPIO_Init(SW_I2C1_SDA_GPIO, &GPIO_InitStructure);
}
//else if(sel==x) ...
}
void scl_in_mode(uint8_t sel)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_OD;
if(sel == 1)
{
GPIO_InitStructure.Pin = SW_I2C1_SCL_PIN;
HAL_GPIO_Init(SW_I2C1_SCL_GPIO, &GPIO_InitStructure);
}
//else if(sel==x) ...
}
void scl_out_mode(uint8_t sel)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_OD;
if(sel == 1)
{
GPIO_InitStructure.Pin = SW_I2C1_SCL_PIN;
HAL_GPIO_Init(SW_I2C1_SCL_GPIO, &GPIO_InitStructure);
}
//else if(sel==x) ...
}
void i2c_clk_data_out(uint8_t sel)
{
scl_high(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
scl_low(sel);
}
void i2c_port_initial(uint8_t sel)
{
sda_high(sel);
scl_high(sel);
}
void i2c_start_condition(uint8_t sel)
{
sda_high(sel);
scl_high(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
sda_low(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
scl_low(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME << 1);
}
void i2c_stop_condition(uint8_t sel)
{
sda_low(sel);
scl_high(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
sda_high(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
}
uint8_t i2c_check_ack(uint8_t sel)
{
uint8_t ack;
int i;
unsigned int temp;
sda_in_mode(sel);
scl_high(sel);
ack = 0;
TIMER__Wait_us(SW_I2C_WAIT_TIME);
for (i = 10; i > 0; i--)
{
temp = !(SW_I2C_ReadVal_SDA(sel));
if (temp)
{
ack = 1;
break;
}
}
scl_low(sel);
sda_out_mode(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
return ack;
}
void i2c_check_not_ack(uint8_t sel)
{
sda_in_mode(sel);
i2c_clk_data_out(sel);
sda_out_mode(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
}
void i2c_check_not_ack_continue(uint8_t sel)
{
i2c_clk_data_out(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
}
void i2c_slave_address(uint8_t sel, uint8_t IICID, uint8_t readwrite)
{
int x;
if (readwrite)
{
IICID |= I2C_READ;
//printf("%d",IICID);
}
else
{
IICID &= ~I2C_READ;
//printf("%d",IICID);
}
scl_low(sel);
for (x = 7; x >= 0; x--)
{
sda_out(sel, IICID & (1 << x));
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_clk_data_out(sel);
}
}
void i2c_register_address(uint8_t sel, uint8_t addr)
{
int x;
scl_low(sel);
for (x = 7; x >= 0; x--)
{
sda_out(sel, addr & (1 << x));
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_clk_data_out(sel);
}
}
void i2c_send_ack(uint8_t sel)
{
sda_out_mode(sel);
sda_low(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
scl_high(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME << 1);
sda_low(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME << 1);
scl_low(sel);
sda_out_mode(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
}
uint8_t SW_I2C_ReadVal_SDA(uint8_t sel)
{
if(sel == 1)
return GPIO_ReadInputDataBit(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN);
return 0;
}
uint8_t SW_I2C_ReadVal_SCL(uint8_t sel)
{
if(sel == 1)
return GPIO_ReadInputDataBit(SW_I2C1_SCL_GPIO, SW_I2C1_SCL_PIN);
return 0;
}
void SW_I2C_Write_Data(uint8_t sel, uint8_t data)
{
int x;
scl_low(sel);
for (x = 7; x >= 0; x--)
{
sda_out(sel, data & (1 << x));
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_clk_data_out(sel);
}
}
uint8_t SW_I2C_Read_Data(uint8_t sel)
{
int x;
uint8_t readdata = 0;
sda_in_mode(sel);
for (x = 8; x--;)
{
scl_high(sel);
readdata <<= 1;
if (SW_I2C_ReadVal_SDA(sel))
readdata |= 0x01;
TIMER__Wait_us(SW_I2C_WAIT_TIME);
scl_low(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
}
sda_out_mode(sel);
return readdata;
}
uint8_t SW_I2C_WriteControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t data)
{
uint8_t returnack = TRUE;
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_register_address(sel, regaddr);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
SW_I2C_Write_Data(sel, data);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_stop_condition(sel);
return returnack;
}
uint8_t SW_I2C_WriteControl_8Bit_OnlyRegAddr(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
uint8_t returnack = TRUE;
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
i2c_register_address(sel, regaddr);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
return returnack;
}
uint8_t SW_I2C_WriteControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint16_t data)
{
uint8_t returnack = TRUE;
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_register_address(sel, regaddr);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
SW_I2C_Write_Data(sel, (data >> 8) & 0xFF);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
SW_I2C_Write_Data(sel, data & 0xFF);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_stop_condition(sel);
return returnack;
}
uint8_t SW_I2C_ReadControl_8Bit_OnlyRegAddr(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
uint8_t returnack = TRUE;
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_register_address(sel, regaddr);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_stop_condition(sel);
return returnack;
}
uint8_t SW_I2C_ReadControl_8Bit_OnlyData(uint8_t sel, uint8_t IICID)
{
uint8_t readdata = 0;
i2c_port_initial(sel);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, READ_CMD);
i2c_check_ack(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
readdata = SW_I2C_Read_Data(sel);
i2c_check_not_ack(sel);
i2c_stop_condition(sel);
return readdata;
}
uint16_t SW_I2C_ReadControl_16Bit_OnlyData(uint8_t sel, uint8_t IICID)
{
uint8_t readimsi = 0;
uint16_t readdata = 0;
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, READ_CMD);
i2c_check_not_ack(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
readimsi = SW_I2C_Read_Data(sel);
i2c_check_not_ack_continue(sel);
readdata = readimsi<<8;
readimsi = SW_I2C_Read_Data(sel);
i2c_check_not_ack(sel);
readdata |= readimsi;
i2c_stop_condition(sel);
return readdata;
}
uint8_t SW_I2C_ReadControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
uint8_t readdata = 0;
i2c_port_initial(sel);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
i2c_check_ack(sel);
i2c_register_address(sel, regaddr);
i2c_check_ack(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, READ_CMD);
i2c_check_ack(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
readdata = SW_I2C_Read_Data(sel);
i2c_check_not_ack(sel);
//i2c_stop_condition(sel);
i2c_start_condition(sel);
return readdata;
}
uint16_t SW_I2C_ReadControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
uint16_t readdata = 0;
i2c_port_initial(sel);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
i2c_check_ack(sel);
i2c_register_address(sel, regaddr);
i2c_check_ack(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, READ_CMD);
i2c_check_ack(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
readdata = SW_I2C_Read_Data(sel);
i2c_send_ack(sel);
TIMER__Wait_us(SW_I2C_WAIT_TIME);
readdata = ((readdata << 8) | SW_I2C_Read_Data(sel));
i2c_check_not_ack(sel);
i2c_stop_condition(sel);
i2c_start_condition(sel); //TODO
i2c_slave_address(sel, IICID, WRITE_CMD);
i2c_check_ack(sel);
i2c_stop_condition(sel);
return readdata;
}
uint8_t SW_I2C_ReadnControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata))
{
uint8_t returnack = TRUE;
uint8_t index;
i2c_port_initial(sel);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
if (!i2c_check_ack(sel)) { returnack = FALSE; }
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_register_address(sel, regaddr);
if (!i2c_check_ack(sel)) { returnack = FALSE; }
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, READ_CMD);
if (!i2c_check_ack(sel)) { returnack = FALSE; }
for ( index = 0 ; index < rcnt ; index++){
TIMER__Wait_us(SW_I2C_WAIT_TIME);
pdata[index] = SW_I2C_Read_Data(sel);
}
pdata[rcnt-1] = SW_I2C_Read_Data(sel);
i2c_check_not_ack(sel);
i2c_stop_condition(sel);
i2c_start_condition(sel); //TODO
i2c_slave_address(sel, IICID, WRITE_CMD);
i2c_check_ack(sel);
i2c_stop_condition(sel);
return returnack;
}
uint8_t SW_I2C_Multi_ReadnControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata))
{
uint8_t returnack = TRUE;
uint8_t index;
i2c_port_initial(sel);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
if (!i2c_check_ack(sel)) { returnack = FALSE; }
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_register_address(sel, regaddr);
if (!i2c_check_ack(sel)) { returnack = FALSE; }
TIMER__Wait_us(SW_I2C_WAIT_TIME);
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, READ_CMD);
if (!i2c_check_ack(sel)) { returnack = FALSE; }
for ( index = 0 ; index < (rcnt-1) ; index++){
TIMER__Wait_us(SW_I2C_WAIT_TIME);
pdata[index] = SW_I2C_Read_Data(sel);
i2c_send_ack(sel);
}
pdata[rcnt-1] = SW_I2C_Read_Data(sel);
i2c_check_not_ack(sel);
i2c_stop_condition(sel);
i2c_start_condition(sel); //TODO
i2c_slave_address(sel, IICID, WRITE_CMD);
i2c_check_ack(sel);
i2c_stop_condition(sel);
return returnack;
}
uint8_t SW_I2C_Check_SlaveAddr(uint8_t sel, uint8_t IICID)
{
uint8_t returnack = TRUE;
i2c_start_condition(sel);
i2c_slave_address(sel, IICID, WRITE_CMD);
if (!i2c_check_ack(sel))
{
returnack = FALSE;
}
return returnack;
}
uint8_t SW_I2C_UTIL_WRITE(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t data)
{
return SW_I2C_WriteControl_8Bit(sel, IICID<<1, regaddr, data);
}
uint8_t SW_I2C_UTIL_Read(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
return SW_I2C_ReadControl_8Bit(sel, IICID<<1, regaddr);
}
uint8_t SW_I2C_UTIL_Read_Multi(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata))
{
return SW_I2C_Multi_ReadnControl_8Bit(sel, IICID<<1, regaddr, rcnt, pdata);
}

View File

@ -0,0 +1,54 @@
#ifndef __I2C_SW_H
#define __I2C_SW_H
/* includes */
#include "hardware.h"
#include "stdio.h"
/* defines */
#define GPIO_SW_I2C1_SCL SWI2C_SCL_GPIO_Port
#define GPIO_SW_I2C1_SDA SWI2C_SDA_GPIO_Port
#define GPIO_SW_I2C1_SCL_PIN SWI2C_SCL_Pin
#define GPIO_SW_I2C1_SDA_PIN SWI2C_SDA_Pin
/*
#define GPIO_SW_I2Cx_SCL GPIOx
#define GPIO_SW_I2Cx_SDA GPIOx
#define GPIO_SW_I2Cx_SCL_PIN GPIO_PIN_x
#define GPIO_SW_I2Cx_SDA_PIN GPIO_PIN_x
*/
#define SW_I2C1 1
//#define SW_I2Cx x
/* functions */
void TIMER__Wait_us(__IO uint32_t uS);
void SW_I2C_initial(void);
void i2c_port_initial(uint8_t sel);
uint8_t SW_I2C_ReadVal_SDA(uint8_t sel);
void SW_I2C_Write_Data(uint8_t sel, uint8_t data);
uint8_t SW_I2C_Read_Data(uint8_t sel);
uint8_t SW_I2C_WriteControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t data);
uint8_t SW_I2C_WriteControl_8Bit_OnlyRegAddr(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint8_t SW_I2C_WriteControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint16_t data);
uint8_t SW_I2C_ReadControl_8Bit_OnlyRegAddr(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint8_t SW_I2C_ReadControl_8Bit_OnlyData(uint8_t sel, uint8_t IICID);
uint16_t SW_I2C_ReadControl_16Bit_OnlyData(uint8_t sel, uint8_t IICID);
uint8_t SW_I2C_ReadControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint16_t SW_I2C_ReadControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint8_t SW_I2C_ReadnControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata));
uint8_t SW_I2C_Multi_ReadnControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata));
uint8_t SW_I2C_Check_SlaveAddr(uint8_t sel, uint8_t IICID);
uint8_t SW_I2C_UTIL_WRITE(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t data);
uint8_t SW_I2C_UTIL_Read(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint8_t SW_I2C_UTIL_Read_Multi(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata));
#endif /* __I2C_SW_H */

View File

@ -0,0 +1,43 @@
# Soft I2C For STM32 using HAL
That is Edited version of [Original version](https://schkorea.tistory.com/437) for stm32
**usage:**
define GPIO in `i2c_sw.h`:
```c
#define GPIO_SW_I2C1_SCL GPIOB
#define GPIO_SW_I2C1_SDA GPIOB
#define GPIO_SW_I2C1_SCL_PIN GPIO_PIN_13
#define GPIO_SW_I2C1_SDA_PIN GPIO_PIN_14
```
That example is for `stm32f103` , for use other micro replace `#include "stm32f1xx_hal_gpio.h"` in `i2c_sw.h`.
This library has the ability to activate more than 10 software I2C , which have been commented in this library, but by default only one of them has been activated.
**Example:**
```c
#include "i2c_sw.h"
int main()
{
SW_I2C_initial();
i2c_port_initial(SW_I2C1);
while(1)
{
//Write DATA to Reg at Reg_Addr from I2C_Add Device connected to SW_I2C1
SW_I2C_WriteControl_8Bit(SW_I2C1,I2C_Add,Reg_Addr,DATA);
//Read DATA at Reg_Add from I2C_Add Device connected to SW_I2C1
DATA=SW_I2C_ReadControl_8Bit(SW_I2C1,I2C_Add,Reg_Add);
}
}
```

View File

@ -0,0 +1,810 @@
#include "KT0915.h"
#define enablePort GPIOB
int deviceAddress = KT0915_I2C_ADDRESS;
int enablePin = GPIO_PIN_0;
uint16_t currentStep; //Stores the current step
uint32_t currentFrequency; //Stores the current frequency
uint32_t minimumFrequency; //Stores the minimum frequency for the current band
uint32_t maximumFrequency; //Stores the maximum frequency for the current band
uint8_t currentMode; //Stores the current mode
uint8_t currentRefClockType = OSCILLATOR_32KHZ; //Stores the crystal type
uint8_t currentRefClockEnabled = REF_CLOCK_DISABLE; //Strores 0 = Crystal; 1 = Reference clock
uint8_t currentDialMode = DIAL_MODE_OFF; //Stores the default Dial Mode (OFF)
uint16_t deviceId;
uint8_t currentVolume = 15;
uint8_t KT0915_getCurrentMode() { return currentMode; };
/* //Set I2C Address
void KT0915_setI2CBusAddress(int N_deviceAddress)
{
deviceAddress = N_deviceAddress;
} */
void KT0915_setRegister(int reg, uint16_t parameter)
{
word16_to_bytes param;
param.raw = parameter;
//SW_I2C_WriteControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint16_t data);
SW_I2C_WriteControl_16Bit(SW_I2C1,deviceAddress,reg,param.raw); //USE SOFT I2C
HAL_Delay(6);
}
uint16_t KT0915_getRegister(int reg)
{
word16_to_bytes result;
//SW_I2C_ReadControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr)
result.refined = SW_I2C_ReadControl_16Bit(SW_I2C1,deviceAddress,reg);
HAL_Delay(6);
return result.raw;
}
uint16_t KT0915_getDeviceId()
{
deviceId = KT0915_getRegister(REG_CHIP_ID);
return deviceId;
}
uint8_t KT0915_isCrystalReady()
{
kt09xx_statusa reg;
reg.raw = KT0915_getRegister(REG_STATUSA);
return reg.refined.XTAL_OK;
}
uint8_t KT0915_PLLStatus()
{
kt09xx_statusa reg;
reg.raw = KT0915_getRegister(REG_STATUSA);
return reg.refined.PLL_LOCK;
}
uint8_t KT0915_LOStatus()
{
kt09xx_statusa reg;
reg.raw = KT0915_getRegister(REG_STATUSA);
return reg.refined.LO_LOCK;
}
/*
* * Crystal type table
* | Dec | binary | Description | defined constant |
* | -- | ------ | ----------- | --------------- |
* | 0 | 0000 | 32.768KHz | OSCILLATOR_32KHZ |
* | 1 | 0001 | 6.5MHz | OSCILLATOR_6_5MHZ |
* | 2 | 0010 | 7.6MHz | OSCILLATOR_7_6MHZ |
* | 3 | 0011 | 12MHz | OSCILLATOR_12MHZ |
* | 4 | 0100 | 13MHz | OSCILLATOR_13MHZ |
* | 5 | 0101 | 15.2MHz | OSCILLATOR_15_2MHZ |
* | 6 | 0110 | 19.2MHz | OSCILLATOR_19_2MHZ |
* | 7 | 0111 | 24MHz | OSCILLATOR_24MHZ |
* | 8 | 1000 | 26MHz | OSCILLATOR_26MHZ |
* | 9 | 1001 | ?? 38KHz ?? | OSCILLATOR_38KHz |
*
*/
void KT0915_setReferenceClockType(uint8_t crystal, uint8_t ref_clock)
{
kt09xx_amsyscfg reg;
reg.raw = KT0915_getRegister(REG_AMSYSCFG); // Gets the current value of the register
reg.refined.REFCLK = crystal; // Changes just crystal parameter
reg.refined.RCLK_EN = ref_clock; // Reference Clock Enable => Crystal
KT0915_setRegister(REG_AMSYSCFG, reg.raw); // Strores the new value to the register
currentRefClockType = crystal;
currentRefClockEnabled = ref_clock;
}
void KT0915_enable(uint8_t on_off)
{
if (on_off == 0) {
return;
} else {
//HAL_GPIO_WritePin(GPIOx,GPIO_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(enablePort,enablePin,GPIO_PIN_SET);
TIMER__Wait_us(10);
}
}
/**
* @ingroup GA03
* @todo You need to check mechanical Tune features
* @brief Sets Tune Dial Mode Interface On
* @details This method sets the KT0915 to deal with a mechanical tuning via an external 100K resistor.
* @details KT0915 supports a unique Dial Mode (mechanical tuning wheel with a variable resistor) which is
* @details enabled by GPIO1 to 2 (10). The dial can be a variable resistor with the tap connected to CH (pin 1).
*
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); pages 19 and 20.
*
* @param minimu_frequency Start frequency for the user band
* @param maximum_frequency Final frequency for the user band
*/
void KT0915_setTuneDialModeOn(uint32_t minimu_frequency, uint32_t maximum_frequency)
{
kt09xx_amsyscfg reg;
kt09xx_gpiocfg gpio;
kt09xx_userstartch uf;
kt09xx_userguard ug;
kt09xx_userchannum uc;
reg.raw = KT0915_getRegister(REG_AMSYSCFG); // Gets the current value from the register
reg.refined.USERBAND = currentDialMode = DIAL_MODE_ON;
KT0915_setRegister(REG_AMSYSCFG, reg.raw); // Strores the new value in the register
gpio.raw = KT0915_getRegister(REG_GPIOCFG); // Gets the current value from the register
gpio.refined.GPIO1 = 2; // Sets Dial Mode interface (pin 1/CH)
KT0915_setRegister(REG_GPIOCFG, gpio.raw); // Stores the new value in the register
// TODO: Sets the frequency limits for user and
if (currentMode == MODE_AM)
{
uf.refined.USER_START_CHAN = minimu_frequency;
uc.refined.USER_CHAN_NUM = (maximum_frequency - minimu_frequency) / currentStep;
ug.refined.USER_GUARD = 0x0011;
}
else
{
uf.refined.USER_START_CHAN = minimu_frequency / 50;
uc.refined.USER_CHAN_NUM = ((maximum_frequency - minimu_frequency) / 50) / currentStep;
ug.refined.USER_GUARD = 0x001D;
}
KT0915_setRegister(REG_USERSTARTCH, uf.raw);
KT0915_setRegister(REG_USERGUARD, ug.raw);
KT0915_setRegister(REG_USERCHANNUM, uc.raw);
};
/**
* @ingroup GA03
* @brief Turns the Tune Dial Mode interface Off
* @see setTuneDialModeOn
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 20.
*/
void KT0915_setTuneDialModeOff()
{
kt09xx_amsyscfg reg;
kt09xx_gpiocfg gpio;
reg.raw = KT0915_getRegister(REG_AMSYSCFG); // Gets the current value of the register
reg.refined.USERBAND = currentDialMode = DIAL_MODE_OFF;
KT0915_setRegister(REG_AMSYSCFG, reg.raw); // Strores the new value to the register
gpio.raw = KT0915_getRegister(REG_GPIOCFG); // Gets the current value of the register
gpio.refined.GPIO1 = 0; // Sets MCU (Arduino) control (High Z)
KT0915_setRegister(REG_GPIOCFG, gpio.raw); // Stores the new value in the register
}
/**
* @ingroup GA03
* @brief Sets Volume Dial Mode Interface On
* @details This method sets the KT0915 to deal with a mechanical volume control via an external 100K resistor.
* @details KT0915 supports a unique Dial Mode which is enabled by GPIO2 to 2 (10).
* @details The dial can be a variable resistor with the tap connected to VOL (pin 16).
*
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 20.
*/
void KT0915_setVolumeDialModeOn()
{
kt09xx_gpiocfg gpio;
gpio.raw = KT0915_getRegister(REG_GPIOCFG); // Gets the current value from the register
gpio.refined.GPIO2 = 2; // Sets Dial Mode interface (pin 16/VOL)
KT0915_setRegister(REG_GPIOCFG, gpio.raw); // Stores the new value in the register
};
/**
* @ingroup GA03
* @brief Turns the Volume Dial Mode interface Off
* @see setVolumeDialModeOn
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 20.
*/
void KT0915_setVolumeDialModeOff()
{
kt09xx_gpiocfg gpio;
gpio.raw = KT0915_getRegister(REG_GPIOCFG); // Gets the current value of the register
gpio.refined.GPIO2 = 0; // Sets to MCU (Arduino) control (High Z)
KT0915_setRegister(REG_GPIOCFG, gpio.raw); // Stores the new value in the register
}
/**
* @ingroup GA03
* @brief Audio Gain
* @details This function set the audio gain you want to use. See table below.
* | value | Gain Selection |
* | ----- | -------------- |
* | 0 | 3dB |
* | 1 | 6dB |
* | 2 | -3dB |
* | 3 | 0dB |
*
* @param gain See table above
*/
void KT0915_setAudioGain(uint8_t gain)
{
kt09xx_amsyscfg r;
r.raw = KT0915_getRegister(REG_AMSYSCFG);
r.refined.AU_GAIN = gain;
KT0915_setRegister(REG_AMSYSCFG, r.raw);
}
/**
* @ingroup GA03
* @brief Sets the audio volume level
* @details This method is used to control the audio volume level. The value 0 mutes the device and 31 sets the device to the maximum volume.
* @param volume between 0 and 31.
*/
void KT0915_setVolume(uint8_t volume)
{
kt09xx_rxcfg rx;
rx.raw = KT0915_getRegister(REG_RXCFG);
rx.refined.VOLUME = volume;
KT0915_setRegister(REG_RXCFG, rx.raw);
currentVolume = volume;
}
/**
* @ingroup GA03
* @brief Increases the audio volume
*
*/
void KT0915_setVolumeUp()
{
if (currentVolume == 31)
return;
KT0915_setVolume(currentVolume + 1);
}
/**
* @ingroup GA03
* @brief Decreases the audio volume
*
*/
void KT0915_setVolumeDown()
{
if (currentVolume == 0)
return;
KT0915_setVolume(currentVolume - 1);
}
/**
* @ingroup GA03
* @brief Returns the current audio volume
* @details Returns a value between 0 and 31.
* @return uint8_t Value between 0 and 31.
*/
uint8_t KT0915_getVolume()
{
return currentVolume;
}
void KT0915_SetStandby(uint8_t on_off)
{
kt09xx_rxcfg rx;
rx.raw = KT0915_getRegister(REG_RXCFG);
rx.refined.STDBY = on_off;
KT0915_setRegister(REG_RXCFG, rx.raw);
}
/**
* @ingroup GA03
* @brief AM and FM Softmute control
* @details The internal KT0915 device register, FM and AM SMUTE 0 means enable and 1 disable. This function inverts this concept. So 1 means enable and 0 disable.
*
* @param on_off 1 = ON (enable); 0 = OFF disable
*/
void KT0915_setSoftMute(uint8_t on_off)
{
kt09xx_volume v;
v.raw = KT0915_getRegister(REG_VOLUME);
v.refined.AMDSMUTE = v.refined.FMDSMUTE = !on_off;
KT0915_setRegister(REG_VOLUME, v.raw); // Stores the new values of the register
}
/**
* @ingroup GA03
* @brief Sets the bass level
* @details Bass Boost Effect Mode Selection
* | Value | Level |
* | ----- | ------- |
* | 0 | Disable |
* | 1 | Low |
* | 2 | Med |
* | 3 | High |
*
* @param on_off see table above
*/
void KT0915_setAudioBass(uint8_t bass)
{
kt09xx_volume v;
v.raw = KT0915_getRegister(REG_VOLUME);
v.refined.BASS = bass;
KT0915_setRegister(REG_VOLUME, v.raw); // Stores the new values of the register
}
/**
* @brief Sets the output audio mute
*
* @param mute_on_off 1 = mute; 0 unmute
*/
void KT0915_setAudioMute(uint8_t mute_on_off)
{
kt09xx_volume v;
v.raw = KT0915_getRegister(REG_VOLUME);
v.refined.DMUTE = !mute_on_off;
KT0915_setRegister(REG_VOLUME, v.raw); // Stores the new values of the register
}
/**
* @ingroup GA03
* @brief Sets Audio DAC Anti-pop Configuration
*
* @details Bass Boost Effect Mode Selection
* | Value | AC - coupling capacitor |
* | ----- | ------------------------- |
* | 0 | 100uF |
* | 1 | 60uF |
* | 2 | 20uF |
* | 3 | 10uF |
*
* @param on_off see table above
*/
void KT091_setAudioAntiPop(uint8_t value)
{
kt09xx_volume v;
v.refined.POP = value;
KT0915_setRegister(REG_VOLUME, v.raw); // Stores the new values of the register
}
/**
* @ingroup GA03
* @brief Sets the Left Channel Inverse Control
* @details If enable, inverts the left channel audio signal
* @details A fully differential audio signal can be got from LOUT an ROUT if the INV_LEFT_AUDIO bit and MONO bit are set to 1.
* @param value ENABLE_ON (1); ENABLE_OFF (0)
*/
void KT0915_setLeftChannelInverseControl(uint8_t enable_disable)
{
kt09xx_amdsp r;
r.raw = KT0915_getRegister(REG_AMDSP);
r.refined.INV_LEFT_AUDIO = enable_disable;
KT0915_setRegister(REG_AMDSP,r.raw);
}
/**
* @ingroup GA03
* @brief Receiver startup
* @details You have to use this method to configure the way that the device will work. For example: enable and disable device control; oscillator type and reference clock type (crystal or external)
* @details The tabe below shows the oscillator frequencies supported by the device.
* @details If you omit the crystal type parameter, will be considered 0 (32.768KHz).
* @details For a low frequency crystal oscillator, selects 32.768KHz or 38KHz crystals.
* @details Alternatively, you can use a CMOS level external reference clock may be used by setting
* @details the parameter ref_clock to 1 (REF_CLOCK_ENABLE) and setting the reference clock according to the table below.
* @details The code below shows how to use the setup function.
* @details the enable_pin parameter sets the way you are controlling the KT0915 pin 9.
*
* @code
* #include <KT0915.h>
* #define RESET_PIN 12 // set it to -1 if you want to use the RST pin of your MCU.
* KT0915 radio;
* void setup() {
* // Set the parameter enablePin to -1 if you are controlling the enable status via circuit; Select OSCILLATOR_32KHZ, OSCILLATOR_12MHZ etc
* // radio.setup(RESET_PIN); Instead the line below, if you use this line, the crystal type considered will be 32.768KHz.
* radio.setup(RESET_PIN, OSCILLATOR_12MHZ, REF_CLOCK_DISABLE );
* }
* @endcode
*
* Oscillator frequencies supported
* | Dec | binary | Description | defined constant |
* | -- | ------ | ----------- | --------------- |
* | 0 | 0000 | 32.768KHz | OSCILLATOR_32KHZ |
* | 1 | 0001 | 6.5MHz | OSCILLATOR_6_5MHZ |
* | 2 | 0010 | 7.6MHz | OSCILLATOR_7_6MHZ |
* | 3 | 0011 | 12MHz | OSCILLATOR_12MHZ |
* | 4 | 0100 | 13MHz | OSCILLATOR_13MHZ |
* | 5 | 0101 | 15.2MHz | OSCILLATOR_15_2MHZ |
* | 6 | 0110 | 19.2MHz | OSCILLATOR_19_2MHZ |
* | 7 | 0111 | 24MHz | OSCILLATOR_24MHZ |
* | 8 | 1000 | 26MHz | OSCILLATOR_26MHZ |
* | 9 | 1001 | 38KHz | OSCILLATOR_38KHz |
*
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); 3.6 Crystal and reference clock; page 9.
* @see setReferenceClockType
*
* @param enablePin if >= 0, then you control the device enable or disable status. if -1, you are using the circuit to crontole that.
* @param oscillator_type oscillator type. You can use crystal or external clock. See comments and table above.
* @param ref_clock set to 0 if you are using crystal (Reference clock disabled - default); set to 1 if you are using an external reference clock.
*/
void KT0915_setup(uint8_t oscillator_type, uint8_t ref_clock)
{
KT0915_enable(1);
HAL_Delay(5);
KT0915_setReferenceClockType(oscillator_type, ref_clock);
KT0915_setVolume(currentVolume);
}
/**
* @defgroup GA04 Tune Methods
* @section GA04 Tune Methods
* @details Methods to tune and set the receiver mode
*/
/**
* @ingroup GA04
* @brief Sets the receiver Stereo or Mono
* @details Set this parameter to true to force mono or false to stereo
* @param on_off true = mono; fale = stereo
*/
void KT0915_setMono(uint8_t on_off)
{
kt09xx_dspcfga reg;
reg.raw = KT0915_getRegister(REG_DSPCFGA);
reg.refined.MONO = on_off;
KT0915_setRegister(REG_DSPCFGA, reg.raw);
}
/**
* @ingroup GA04
* @brief Return true if the stereo indicator is set to 3;
* @return true is stereo
*/
uint8_t KT0915_isFmStereo()
{
kt09xx_statusa r;
r.raw = KT0915_getRegister(REG_STATUSA);
return (r.refined.ST == 3);
}
/**
* @ingroup GA04
* @brief Gets the current FM RSSI
*
* @return int RSSI value
*/
int KT0915_getFmRssi()
{
kt09xx_statusa r;
r.raw = KT0915_getRegister(REG_STATUSA);
return (r.refined.FMRSSI * 3);
};
/**
* @ingroup GA04
* @brief Gets the current AM RSSI
*
* @return int RSSI value
*/
int KT0915_getAmRssi()
{
kt09xx_amdstatusa r;
r.raw = KT0915_getRegister(REG_AMSTATUSA);
return (r.refined.AMRSSI * 3);
};
/**
* @ingroup GA04
* @brief Gets current SNR value
*
* @return int FM SNR value
*/
int KT0915_getFmSnr()
{
kt09xx_statusc r;
r.raw = KT0915_getRegister(REG_STATUSC);
return (r.refined.FMSNR);
};
/**
* @ingroup GA04
* @brief Sets the De-emphasis Time Constant Selection
* @param value 0 = 75us; 1 = 50us
*/
void KT0915_setDeEmphasis(uint8_t value)
{
kt09xx_dspcfga reg;
reg.raw = KT0915_getRegister(REG_DSPCFGA);
reg.refined.DE = value;
KT0915_setRegister(REG_DSPCFGA, reg.raw);
}
/**
* @ingroup GA04
* @brief Sets FM AFC Disable Control
* @details This function inverts the register enable/disable concept. So, here, 1 means enable and 0 disable.
* @param on_off 1 = enable AFC; 0 = disable AFC.
*/
void KT0915_setFmAfc(uint8_t on_off)
{
kt09xx_locfga r;
r.refined.FMAFCD = !on_off;
KT0915_setRegister(REG_LOCFGA, r.raw);
}
/**
* @ingroup GA04
* @brief Sets AM AFC Disable Control
* @details This function inverts the register enable/disable concept. So, here, 1 means enable and 0 disable.
* @param on_off 1 = enable AFC; 0 = disable AFC.
*/
void KT0915_setAmAfc(uint8_t on_off)
{
kt09xx_amsyscfg r;
r.raw = KT0915_getRegister(REG_AMSYSCFG); // Gets the current value of the register
r.refined.RESERVED1 = 1;
r.refined.AMAFCD = !on_off;
KT0915_setRegister(REG_AMSYSCFG, r.raw);
}
/**
* @ingroup GA04
* @brief Sets the AM Space
* @details Selects AM channel space
*
* | value | space |
* | ----- | ----- |
* | 0 | 1KHz |
* | 1 | 9KHz |
* | 2 | 10KHz |
* | 3 | 10KHz |
*
* @param value See table above
*/
void KT0915_setAmSpace(uint8_t value)
{
kt09xx_amcfg r;
r.raw = KT0915_getRegister(REG_AMCFG);
r.refined.AMSPACE = value;
KT0915_setRegister(REG_AMCFG, r.raw);
}
/**
* @ingroup GA04
* @brief Sets AM Channel Bandwidth Selection
* @details Configures the AM Bandwidth
*
* | value | Bandwidth |
* | ----- | --------- |
* | 0 | 2KHz |
* | 1 | 2KHz |
* | 2 | 4KHz |
* | 3 | 6KHz |
*
* @param value See table above
*/
void KT0915_setAmBandwidth(uint8_t value)
{
kt09xx_amdsp r;
r.raw = KT0915_getRegister(REG_AMDSP);
r.refined.AM_BW = value;
KT0915_setRegister(REG_AMDSP, r.raw);
}
/**
* @ingroup GA04
* @brief Gets current AM Channel Bandwidth Selection
*
* | value | Bandwidth |
* | ----- | --------- |
* | 0 | 2KHz |
* | 1 | 2KHz |
* | 2 | 4KHz |
* | 3 | 6KHz |
*
* @return See table above
*/
uint8_t KT0915_getAmBandwidth()
{
kt09xx_amdsp r;
r.raw = KT0915_getRegister(REG_AMDSP);
return r.refined.AM_BW;
}
/**
* @todo Adjust setTuneDialOn()
* @ingroup GA04
* @brief Sets the receiver to FM mode
* @details Configures the receiver on FM mode; Also sets the band limits, defaul frequency and step.
*
* @param minimum_frequency minimum frequency for the band
* @param maximum_frequency maximum frequency for the band
* @param default_frequency default freuency
* @param step increment and decrement frequency step
*/
void KT0915_setFM(uint32_t minimum_frequency, uint32_t maximum_frequency, uint32_t default_frequency, uint16_t step)
{
kt09xx_amsyscfg reg;
currentStep = step;
currentFrequency = default_frequency;
minimumFrequency = minimum_frequency;
maximumFrequency = maximum_frequency;
currentMode = MODE_FM;
reg.raw = KT0915_getRegister(REG_AMSYSCFG);
reg.refined.AM_FM = MODE_FM;
reg.refined.USERBAND = currentDialMode;
reg.refined.REFCLK = currentRefClockType;
reg.refined.RCLK_EN = currentRefClockEnabled;
KT0915_setRegister(REG_AMSYSCFG, reg.raw); // Stores the new value in the register
if (currentDialMode == DIAL_MODE_ON)
KT0915_setTuneDialModeOn(minimum_frequency, maximum_frequency);
else
KT0915_setFrequency(default_frequency);
};
/**
* @todo Adjust setTuneDialOn()
* @ingroup GA04
* @brief Sets the receiver to AM mode
* @details Configures the receiver on AM mode; Also sets the band limits, defaul frequency and step.
*
* @param minimum_frequency minimum frequency for the band
* @param maximum_frequency maximum frequency for the band
* @param default_frequency default freuency
* @param step increment and decrement frequency step
*/
void KT0915_setAM(uint32_t minimum_frequency, uint32_t maximum_frequency, uint32_t default_frequency, uint16_t step, uint8_t am_space)
{
kt09xx_amsyscfg reg;
currentStep = step;
currentFrequency = default_frequency;
minimumFrequency = minimum_frequency;
maximumFrequency = maximum_frequency;
currentMode = MODE_AM;
reg.raw = KT0915_getRegister(REG_AMSYSCFG);
reg.refined.AM_FM = MODE_AM;
reg.refined.USERBAND = currentDialMode;
reg.refined.REFCLK = currentRefClockType;
reg.refined.RCLK_EN = currentRefClockEnabled;
KT0915_setRegister(REG_AMSYSCFG, reg.raw); // Stores the new value in the register
KT0915_setAmSpace(am_space);
if (currentDialMode == DIAL_MODE_ON)
KT0915_setTuneDialModeOn(minimum_frequency, maximum_frequency);
else
KT0915_setFrequency(default_frequency);
}
/**
* @ingroup GA04
* @brief Sets the current frequency
*
* @param frequency
*/
void KT0915_setFrequency(uint32_t frequency)
{
kt09xx_amchan reg_amchan;
kt09xx_tune reg_tune;
if (currentMode == MODE_AM)
{
reg_amchan.refined.AMTUNE = 1; // TODO Check
reg_amchan.refined.AMCHAN = frequency;
KT0915_setRegister(REG_AMCHAN, reg_amchan.raw);
}
else
{
reg_tune.refined.FMTUNE = 1; // // TODO Check
reg_tune.refined.RESERVED = 0;
reg_tune.refined.FMCHAN = frequency / 50;
KT0915_setRegister(REG_TUNE, reg_tune.raw);
}
currentFrequency = frequency;
TIMER__Wait_us(30);
}
/**
* @ingroup GA04
* @brief Increments the frequency one step
* @details if the frequency plus the step value is greater than the maximum frequency for the band,
* @details tne current frequency will be set to minimum frequency.
*
* @see setFrequency
*/
void KT0915_frequencyUp()
{
currentFrequency += currentStep;
if (currentFrequency > maximumFrequency)
currentFrequency = minimumFrequency;
KT0915_setFrequency(currentFrequency);
}
/**
* @ingroup GA04
* @brief Decrements the frequency one step
* @details if the frequency minus the step value is less than the minimum frequency for the band,
* @details tne current frequency will be set to minimum frequency.
*
* @see setFrequency
*/
void KT0915_frequencyDown()
{
currentFrequency -= currentStep;
if (currentFrequency < minimumFrequency)
currentFrequency = maximumFrequency;
KT0915_setFrequency(currentFrequency);
};
/**
* @ingroup GA04
* @brief Sets the frequency step
* @details Sets increment and decrement frequency
* @param step Values: 1, 5, 9, 10, 100, 200 in KHz
*/
void KT0915_setStep(uint16_t step)
{
currentStep = step;
}
/**
* @ingroup GA04
* @brief Gets the current frequency
* @return frequency in KHz
*/
uint32_t KT0915_getFrequency()
{
return currentFrequency;
}
/**
* @ingroup GA04
* @brief Gets the FM Channel Setting
* @details This method returns the current channel value for FM tune.
* @details The channel value multiplied by 50 is the current FM frequency in KHz.
* @return FM Channel number
*/
uint16_t KT0915_getFmCurrentChannel() {
kt09xx_tune r;
r.raw = KT0915_getRegister(REG_TUNE);
return r.refined.FMCHAN;
};
/**
* @ingroup GA04
* @brief Gets the current AM Channel Setting
* @details This method returns the current channel value for AM tune
* @details Actually this value is the AM current frequency in KHz
* @return AM Channel number (frequency in KHz)
*/
uint16_t KT0915_getAmCurrentChannel() {
kt09xx_amchan r;
r.raw = KT0915_getRegister(REG_AMCHAN);
return r.refined.AMCHAN;
};
/**
* @todo Not enough information to do this so far.
* @ingroup GA04
* @brief Should Seek a station
* @details However, there no enough information to implement it.
*/
void KT0915_seekStation()
{
// TODO
}

View File

@ -0,0 +1,582 @@
/**
* @mainpage PU2CLR KT0915 Arduino Library
* @brief PU2CLR KT0915 Arduino Library implementation. <br>
* @details This is an Arduino library for the KT0915, BROADCAST RECEIVER.<br>
* @details It works with I2C protocol and can provide an easier interface for controlling the KT0915 device.<br>
* @details This library was built based on KT0915 Datasheet from KTMicro (Monolithic Digital FM/MW/SW/LW Receiver Radio-on-a-Chip TM).
* @details Others sources help the author to build this library. They are referenced in the documentation for this library on: https://github.com/pu2clr/KT0915
* @details This library uses the I2C protocols to read and write KT0915 registers. In this context, registers are memory position into the device.
* @details The KT0915 is a full band AM (LW, MW and SW) and FM DSP receiver that can provide you a easy way to build a high quality radio with low cost.
* @details This device, will surprise hobbyists and experimenters with its simplicity.
*
* This library can be freely distributed using the MIT Free Software model.
*
* Copyright (c) 2020 Ricardo Lima Caratti.
* Contact: pu2clr@gmail.com
*/
/* #include <Arduino.h>
#include <Wire.h> */
#include "hardware.h"
#include "i2c_sw.h"
#define KT0915_I2C_ADDRESS 0x6A //arduino:0x35 It is needed to check it when the KT0915 device arrives.
#define MODE_FM 0
#define MODE_AM 1
#define TURN_ON 1
#define TURN_OFF 0
#define ENABLE_ON 1
#define ENABLE_OFF 0
#define DE_EMPHASIS_75 0
#define DE_EMPHASIS_50 1
#define OSCILLATOR_32KHZ 0 // 32.768KHz
#define OSCILLATOR_6_5MHZ 1 // 6.5MHz
#define OSCILLATOR_7_6MHZ 2 // 7.6MHz
#define OSCILLATOR_12MHZ 3 // 12MHz
#define OSCILLATOR_13MHZ 4 // 13MHz
#define OSCILLATOR_15_2MHZ 5 // 15.2MHz
#define OSCILLATOR_19_2MHZ 6 // 19.2MHz
#define OSCILLATOR_24MHZ 7 // 24MHz
#define OSCILLATOR_26MHZ 8 // 26MHz
#define OSCILLATOR_38KHz 9 // 38KHz
#define REF_CLOCK_ENABLE 1 // Reference Clock
#define REF_CLOCK_DISABLE 0 // Crystal Clock
#define DIAL_MODE_ON 1 // Mechanical tuning (Via 100K resistor)
#define DIAL_MODE_OFF 0 // MCU (Arduino) tuning
#define REG_CHIP_ID 0x01
#define REG_SEEK 0x02
#define REG_TUNE 0x03
#define REG_VOLUME 0x04
#define REG_DSPCFGA 0x05
#define REG_LOCFGA 0x0A
#define REG_LOCFGC 0x0C
#define REG_RXCFG 0x0F
#define REG_STATUSA 0x12
#define REG_STATUSB 0x13
#define REG_STATUSC 0x14
#define REG_AMSYSCFG 0x16
#define REG_AMCHAN 0x17
#define REG_AMCALI 0x18
#define REG_GPIOCFG 0x1D
#define REG_AMDSP 0x22
#define REG_AMSTATUSA 0x24
#define REG_AMSTATUSB 0x25
#define REG_SOFTMUTE 0x2E
#define REG_USERSTARTCH 0x2F
#define REG_USERGUARD 0x30
#define REG_USERCHANNUM 0x31
#define REG_AMCFG 0x33
#define REG_AMCFG2 0x34
#define REG_AFC 0x3C
//typedef uint8_t bool;
/**
* @defgroup GA01 Union, Structure and Defined Data Types
* @brief KT0915 Defined Data Types
* @details Defined Data Types is a way to represent the KT0915 registers information
* @details Some information appears to be inaccurate due to translation problems from Chinese to English.
* @details The information shown here was extracted from Datasheet:
* @details KT0915 stereo FM / TV / MW / SW / LW digital tuning radio documentation.
* @details Other information seems incomplete even in the original Chinese Datasheet.
* @details For example: Reg 10 (0x0A). There is no information about it. The Reg11 and 12 seem wrong
*/
/**
* @ingroup GA01
* @brief 3.10.1. CHIP ID (Address 0x01)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 15.
*/
typedef union {
uint16_t chip_id;
char chip_id_ascii[2];
} kt09xx_chip_id;
/**
* @ingroup GA01
* @brief 3.10.2. SEEK (Address 0x02)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 15.
*/
typedef union {
struct
{
uint8_t DMUTEL : 1; //!< Left Channel Mute Control; 0 = Left channel mute enable; 1 = Left channel mute disable
uint8_t DMUTER : 1; //!< Right Channel Mute Control; 0 = Left channel mute enable; 1 = Left channel mute disable
uint8_t FMSPACE : 2; //!< FM Channel Spacing; 00 = 200KHz; 01 = 100KHz; 10 = 50KHz
uint16_t RESERVED : 11; //!< Reserved
} refinied;
uint16_t raw;
} kt09xx_seek;
/**
* @ingroup GA01
* @brief 3.10.3. TUNE (Address 0x03)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 15.
*/
typedef union {
struct
{
uint16_t FMCHAN : 12; //!< FM Channel Setting FMCHAN<11:0>=Frequency (KHz) / 50KHz. For example, if desired channel is 86MHz, then the FMCHAN<11:0> should be 0x06B8.
uint8_t RESERVED : 3; //!< Reserved
uint8_t FMTUNE : 1; //!< FM Tune Enable; 0 = Normal operation 1 = Start to tune to desired FM channel
} refined;
uint16_t raw;
} kt09xx_tune;
/**
* @ingroup GA01
* @brief 3.10.4. VOLUME (Address 0x04)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 15/16.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 4; //!< Reserved
uint8_t POP : 2; //!< Audio DAC Anti - pop Configuration00 : 100uF AC - coupling capacitor 01 : 10 : 11 : Reserved 60uF AC - coupling capacitor 20uF AC - coupling capacitor 10uF AC - coupling capacitor.
uint8_t RESERVED2 : 2; //!< Reserved
uint8_t BASS : 2; //!< Bass Boost Effect Mode Selection; 00 = Disable; 01 = Low ; 10 = Med; 11 = High.
uint8_t RESERVED3 : 3; //!< Reserved
uint8_t DMUTE : 1; //!< Mute Disable; 0 = Mute enable; 1 = Mute disable.
uint8_t AMDSMUTE : 1; //!< AM Softmute Disable; 0 = AM softmute enable; 1 = AM softmute disable.
uint8_t FMDSMUTE : 1; //!< AM Softmute Disable; 0 = FM softmute enable; 1 = FM softmute disable.
} refined;
uint16_t raw;
} kt09xx_volume;
/**
* @ingroup GA01
* @brief 3.10.5. DSPCFGA (Address 0x05)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 16/17.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 5; //!< Reserved
uint8_t DBLND : 1; //!< Blend disable; 0 = Blend enable; 1 = Blend disable
uint8_t RESERVED2 : 2; //!< Reserved
uint8_t BLNDADJ : 2; //! Stereo/Mono Blend; Level Adjustment 00 = High; 01 = Highest 10; = Lowest 11 = Low
uint8_t RESERVED3 : 1; //!< Reserved
uint8_t DE : 1; //!< De-emphasis Time Constant Selection. 0 = 75us; 1 = 50us.
uint8_t RESERVED4 : 3; //!< Reserved
uint8_t MONO : 1; //!< Mono Select; 0 = Stereo; 1 = Force mono
} refined;
uint16_t raw;
} kt09xx_dspcfga;
/**
* @ingroup GA01
* @brief 3.10.6. LOCFGA (Address 0x0A)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 17.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 8; //!< Reserved
uint8_t FMAFCD : 1; //!< AFC Disable Control Bit; 0 = AFC enable; 1 = AFC disable.
uint8_t RESERVED2 : 7; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_locfga; // LOCFGA
/**
* @ingroup GA01
* @brief 3.10.7. LOCFGC (Address 0x0C)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 17.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 3; //!< Reserved
uint8_t CAMPUSBAND_EN : 1; //!< Campus FM Band Enable; 0 = User can only use 64MHz ~110MHz; 1 = User can extend the FM band down to 32MHz
uint16_t RESERVED2 : 12; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_locfgc; // LOCFGC
/**
* @ingroup GA01
* @brief 3.10.8. RXCFG (Address 0x0F)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 17.
*/
typedef union {
struct
{
uint8_t VOLUME : 5; //!< Volume Control 11111 = 0dB 11110 = -2dB 11101 = -4dB .... 00010 = -58dB 00001 = -60dB 00000 = Mute
uint8_t RESERVED1 : 7; //!< Campus FM Band Enable; 0 = User can only use 64MHz ~110MHz; 1 = User can extend the FM band down to 32MHz
uint8_t STDBY : 1; //!< Standby Mode Enable. 0 = Disable; 1 = Enable
uint8_t RESERVED2 : 3; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_rxcfg; // RXCFG
/**
* @ingroup GA01
* @brief 3.10.19. STATUSA (Address 0x12)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 18.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 3; //!< Reserved
uint8_t FMRSSI : 5; //!< FM RSSI Value Indicator; RSSI starts from -100dBm and step is 3dB namely; RSSI(dBm) = -100 + FMRSSI<4:0> *3dB
uint8_t ST : 2; //!< Stereo Indicator; 11 = Stereo state; Other = Mono state
uint8_t LO_LOCK : 1; //!< LO Synthesizer Ready Indicator; 0 = Not ready; 1 = Ready
uint8_t PLL_LOCK : 1; //!< System PLL Ready Indicator; 0 = Not ready; 1 = System PLL ready
uint8_t RESERVED2 : 2; //!< Reserved
uint8_t STC : 1; //!< Seek/Tune Complete; 0 = Not Complete; 1 = Complete; Every time the Seek/tune process begins, the STC bit will clear to zero by hardware.
uint8_t XTAL_OK : 1; //!< Crystal ready indictor; 0 = Not ready; 1 = Crystal is ok
} refined;
uint16_t raw;
} kt09xx_statusa; // STATUSA
/**
* @ingroup GA01
* @brief 3.10.10. STATUSB (Address 0x13)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 18.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 1; //!< Reserved
uint16_t RDCHAN : 15; //!< Current Channel Indicator
} refined;
uint16_t raw;
} kt09xx_statusb; // STATUSB
/**
* @ingroup GA01
* @brief 3.10.11. STATUSC (Address 0x14)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 18/19.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 6; //!< Reserved
uint8_t FMSNR : 7; //!< Channel SNR value is FM mode.; 0000000 = Minimum SNR; 1111111 = Maximum SNR
uint8_t CHIPRDY : 1; //!< Chip Ready Indicator; 0 = Chip is not ready; 1 = Chip is ready, calibration done
uint8_t RESERVED2 : 1; //!< Reserved
uint8_t PWSTATUS : 1; //!< Power Status Indicator; 0 = Power not ready; 1 = Power ready
} refined;
uint16_t raw;
} kt09xx_statusc; // STATUSC
/**
* @ingroup GA01
* @brief 3.10.12. AMSYSCFG (Address 0x16)
* @details The table below shows REFCLK possibvle values
*
* Crystal type table
* | Dec | binary | Description | defined constant |
* | -- | ------ | ----------- | --------------- |
* | 0 | 0000 | 32.768KHz | OSCILLATOR_32KHZ |
* | 1 | 0001 | 6.5MHz | OSCILLATOR_6_5MHZ |
* | 2 | 0010 | 7.6MHz | OSCILLATOR_7_6MHZ |
* | 3 | 0011 | 12MHz | OSCILLATOR_12MHZ |
* | 4 | 0100 | 13MHz | OSCILLATOR_13MHZ |
* | 5 | 0101 | 15.2MHz | OSCILLATOR_15_2MHZ |
* | 6 | 0110 | 19.2MHz | OSCILLATOR_19_2MHZ |
* | 7 | 0111 | 24MHz | OSCILLATOR_24MHZ |
* | 8 | 1000 | 26MHz | OSCILLATOR_26MHZ |
* | 9 | 1001 | ?? 38KHz ?? | OSCILLATOR_38KHz |
*
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 19.
*
*/
typedef union {
struct
{
uint8_t AMAFCD : 1; //!< AFC Disable Control in AM Mode; 0 = Enable; 1 = Disable
uint8_t RESERVED1 : 5; //!< Reserved
uint8_t AU_GAIN : 2; //!< Audio Gain Selection; 01 = 6dB; 00 = 3dB; 11 = 0dB; 10 = -3dB
uint8_t REFCLK : 4; //!< See Crystal type table
uint8_t RCLK_EN : 1; //!< Reference Clock Enable; 0 = Crystal; 1 = Reference clock
uint8_t RESERVED2 : 1; //!< Reserved
uint8_t USERBAND : 1; //!< User Definition Band Enable; 0 = Use internal defined band; 1 = Use user-defined band which is specified in USER_START_CHAN<14:0>, USER_GUARD<8:0> and USER_CHAN_NUM<11:0>
uint8_t AM_FM : 1; //!< AM/FM Mode Control; 0 = FM mode; 1 = AM mode
} refined;
uint16_t raw;
} kt09xx_amsyscfg; // AMSYSCFG
/**
* @ingroup GA01
* @brief 3.10.13. AMCHAN (Address 0x17)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 20.
*/
typedef union {
struct
{
uint16_t AMCHAN : 15; //!< AM Channel Setting; AMCHAN<14:0> = Frequency(in KHz)
uint8_t AMTUNE : 1; //!< AM Tune Enable
} refined;
uint16_t raw;
} kt09xx_amchan; // AMCHAN
/**
* @ingroup GA01
* @brief 3.10.14. AMCALI (Address 0x18)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 20.
*/
typedef union {
struct
{
uint16_t CAP_INDEX : 14; //!< On Chip Capacitor for AM Antenna Calibration; 0x0000 = Minimum capacitor; 0x3FFF = Maximum capacitor
uint8_t RESERVED1 : 2; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_amcali; // AMCALI
/**
* @ingroup GA01
* @brief 3.10.15. GPIOCFG (Address 0x1D)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 20.
*/
typedef union {
struct
{
uint8_t GPIO1 : 2; //!< CH Pin Mode Selection; 00 = High Z; 01 = Key controlled channel increase / decrease; 10 = Dial controlled channel increase / decrease; 11 = Reserved
uint8_t GPIO2 : 2; //!< VOL Pin Mode Selection; 00 = High Z; 01 = Key controlled volume increase/decrease; 10 = Dial controlled volume increase/decrease; 11 = Reserved
uint16_t RESERVED : 12; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_gpiocfg; // GPIOCFG
/**
* @ingroup GA01
* @brief 3.10.16. AMDSP (Address 0x22)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); pages 20 and 21.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 3; //!< Reserved
uint8_t INV_LEFT_AUDIO : 1; //!< Left channel inverse control; 0 = Normal operation; 1 = Inversing the left channel audio signal
uint8_t RESERVED2 : 2; //!< Reserved
uint8_t AM_BW : 2; //!< AM Channel Bandwidth Selection; 00 = 2KHz; 01 = 2KHz; 10 = 4KHz; 11 = 6KHz
uint8_t RESERVED3 : 8; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_amdsp; // AMDSP
/**
* @ingroup GA01
* @brief 3.10.17. AMSTATUSA (Address 0x24)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 21.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 8; //!< Reserved
uint8_t AMRSSI : 5; //!< AM Channel RSSI; AM RSSI starts from -90dBm and step is 3dB, namely AMRSSI(dBm) = -90 + AMRSSI<4:0> *3dB
uint8_t RESERVED2 : 3; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_amdstatusa; // AMSTATUSA
/**
* @ingroup GA01
* @brief 3.10.18. AMSTATUSB (Address 0x25)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 21.
*/
typedef union {
struct
{
uint8_t AM_AFCDELTAF : 8; //!< Signed binary, max 16KHz , min -16KHz, step is 128Hz.
uint8_t RESERVED : 8; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_amdstatusb; // AMSTATUSB
/**
* @ingroup GA01
* @brief 3.10.19. SOFTMUTE (Address 0x2Eh)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 21.
*/
typedef union {
struct
{
uint8_t FM_SMTH : 3; //!< FM Softmute Start Threshold; 000 = Lowest ... 111 = Highest
uint8_t SMMD : 1; //!< Softmute Mode Selection; 0 = RSSI mode; 1 = SNR mode (only effective in FM mode)
uint8_t VOLUMET : 5; //!< Softmute target Volume. 0 = RSSI; 1 = SNR mode (only effective in FM mode)
uint8_t AM_SMTH : 3; //!< AM Softmute Start Level. 000 = Lowest ... 111 = Highest
uint8_t SMUTER : 2; //!< Softmute Attack/Recover Rate; 00 = Slowest; 01 = Fastest (RSSI mode only); 10 = Fast; 11 = Slow
uint8_t SMUTEA : 2; //!< Softmute Attenuation; 00 = Strong; 01 = Strongest; 10 = Weak; 11 = Weakest
} refined;
uint16_t raw;
} kt09xx_softmute; // SOFTMUTE
/**
* @ingroup GA01
* @brief 3.10.20. USERSTARTCH (Address 0x2F)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 22.
*/
typedef union {
struct
{
uint16_t USER_START_CHAN : 15; //!< User band start channel, only effect when USERBAND=1. See section 3.7.3. of the Datasheet
uint8_t RESERVED : 1; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_userstartch; // USERSTARTCH
/**
* @ingroup GA01
* @brief 3.10.21. USERGUARD (Address 0x30)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio on a Chip(TM); page 22.
*/
typedef union {
struct
{
uint16_t USER_GUARD : 9; //!< User band guard number, only effective when USERBAND=1. See section 3.7.2.
uint8_t RESERVED : 7; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_userguard; // USERGUARD
/**
* @ingroup GA01
* @brief 3.10.22. USERCHANNUM (Address 0x31)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio-on-a-Chip(TM); page 22.
*/
typedef union {
struct
{
uint16_t USER_CHAN_NUM : 12; //!< User band channel number, only effective when USERBAND=1. See section 3.7.3.
uint8_t RESERVED : 4; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_userchannum; // USERCHANNUM
/**
* @ingroup GA01
* @brief 3.10.23. AMCFG (Address 0x33)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio-on-a-Chip(TM); page 23.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 5; //!< Reserved
uint8_t KEY_MODE : 2; //!< Working mode selection when key mode is selected. 00 = Working mode A; 01 = Working mode B Others = Reserved; For detailed information about working mode A and working mode B, please refer to section 3.7.1.
uint8_t RESERVED2 : 7; //!< Reserved
uint8_t AMSPACE : 2; //!< AM Channel Space Selection; 00 = 1KHz; 01 = 9KHz; 10 = 10KHz; 11 = 10KHz.
} refined;
uint16_t raw;
} kt09xx_amcfg; // AMCFG
/**
* @ingroup GA01
* @brief 3.10.24. AMCFG2 (Address 0x34h)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio-on-a-Chip(TM); page 23.
*/
typedef union {
struct
{
uint8_t RESERVED1 : 1; //!< Reserved
uint8_t TIME2 : 3; //!< 000 = Fastest...... 111 = Slowest
uint8_t TIME1 : 2; //!< 00 = Shortest...... 11 = Longest
uint16_t RESERVED2 : 10; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_amcfg2; // AMCFG2
/**
* @ingroup GA01
* @brief 3.10.25. AFC (Address 0x3Ch)
* @see KT0915; Monolithic Digital FM/MW/SW/LW Receiver Radio-on-a-Chip(TM); page 23.
*/
typedef union {
struct
{
uint8_t FM_AFC_DELTAF : 8; //!< Frequency difference between CHAN and received signal, calculated by AFC block in twos complement format. Range is - 127 to +127. Unit is KHz. This register is valid when STC=1
uint8_t RESERVED1 : 8; //!< Reserved
} refined;
uint16_t raw;
} kt09xx_afc; // AFC
/**
* @ingroup GA01
* @brief Converts 16 bits word to two bytes
*/
typedef union {
uint16_t refined;
uint16_t raw;
} word16_to_bytes;
void KT0915_setRegister(int reg, uint16_t parameter);
uint16_t KT0915_getRegister(int reg);
uint16_t KT0915_getDeviceId(void);
void KT0915_enable(uint8_t on_off);
// void KT0915_setI2CBusAddress(int N_deviceAddress); //TODO CHECK
void KT0915_setReferenceClockType(uint8_t crystal, uint8_t ref_clock);
uint8_t KT0915_isCrystalReady(void);
void KT0915_setup(uint8_t oscillator_type, uint8_t ref_clock);
void KT0915_setTuneDialModeOn(uint32_t minimu_frequency, uint32_t maximum_frequency);
void KT0915_setTuneDialModeOff(void);
void KT0915_setVolumeDialModeOn(void);
void KT0915_setVolumeDialModeOff(void);
void KT0915_setAudioGain(uint8_t gain);
void KT0915_setLeftChannelInverseControl(uint8_t enable_disable);
void KT0915_setVolume(uint8_t value);
void KT0915_setVolumeUp(void);
void KT0915_setVolumeDown(void);
uint8_t KT0915_getVolume(void);
void KT0915_SetStandby(uint8_t on_off);
void KT0915_setSoftMute(uint8_t on_off);
void KT0915_setAudioBass(uint8_t bass);
void KT0915_setAudioAntiPop(uint8_t value);
void KT0915_setAudioMute(uint8_t mute_on_off);
void KT0915_setDeEmphasis(uint8_t value);
void KT0915_setMono(uint8_t on_off);
void KT0915_setFmAfc(uint8_t on_off);
void KT0915_setAmAfc(uint8_t on_off);
void KT0915_setFM(uint32_t minimum_frequency, uint32_t maximum_frequency, uint32_t default_frequency, uint16_t step);
void KT0915_setAM(uint32_t minimum_frequency, uint32_t maximum_frequency, uint32_t default_frequency, uint16_t step, uint8_t am_space);
void KT0915_setAmSpace(uint8_t value);
void KT0915_setAmBandwidth(uint8_t value);
uint8_t KT0915_getAmBandwidth(void);
uint8_t KT0915_isFmStereo(void); //bool
void KT0915_setFrequency(uint32_t frequency);
void KT0915_setStep(uint16_t step);
void KT0915_frequencyUp(void);
void KT0915_frequencyDown(void);
inline void KT0915_setFrequencyUp() { KT0915_frequencyUp(); }; // Just an alias
inline void KT0915_setFrequencyDown() { KT0915_frequencyDown(); }; // Just an alias
uint32_t KT0915_getFrequency(void);
uint16_t KT0915_getFmCurrentChannel(void);
uint16_t KT0915_getAmCurrentChannel(void);
void KT0915_seekStation(void);
int KT0915_getFmRssi(void);
int KT0915_getAmRssi(void);
int KT0915_getFmSnr(void);
uint8_t KT0915_PLLStatus(void);
uint8_t KT0915_LOStatus(void);