test in progress

This commit is contained in:
Sheikah
2023-01-19 00:11:51 +08:00
commit b5cdb2d335
1163 changed files with 636480 additions and 0 deletions

387
Core/APP/app.c Normal file
View File

@ -0,0 +1,387 @@
#include <app.h>
#include <main.h>
#include <st7735.h>
#include <RotaryCoder.h>
#include <KT0915.h>
uint8_t app_setup(void){
}
/*
Shows the static content on display
*/
void showTemplate()
{
int maxX1 = tft.width() - 2;
int maxY1 = tft.height() - 5;
tft.fillScreen(COLOR_BLACK);
tft.drawRect(2, 2, maxX1, maxY1, COLOR_YELLOW);
tft.drawLine(2, 40, maxX1, 40, COLOR_YELLOW);
tft.drawLine(2, 60, maxX1, 60, COLOR_YELLOW);
}
void clearStatus()
{
char *unit;
char *bandMode;
int maxX1 = tft.width() - 6;
int maxY1 = tft.height() - 6;
tft.fillRect(3, 3, maxX1, 35, COLOR_BLACK);
// tft.fillRect(3,61,maxX1, maxY1 - 61, COLOR_BLACK);
if (band[bandIdx].mode == MODE_FM)
{
unit = (char *)"MHz";
bandMode = (char *)"FM";
}
else
{
unit = (char *)"KHz";
bandMode = (char *)"AM";
}
tft.setFont(&Serif_plain_7);
printValue(135, 15, oldMode, bandMode, 7, COLOR_YELLOW);
printValue(135, 36, oldUnit, unit, 7, COLOR_YELLOW);
}
/*
Prevents blinking during the frequency display.
Erases the old digits if it has changed and print the new digit values.
*/
void printValue(int col, int line, char *oldValue, char *newValue, uint8_t space, uint16_t color)
{
int c = col;
char *pOld;
char *pNew;
pOld = oldValue;
pNew = newValue;
// prints just changed digits
while (*pOld && *pNew)
{
if (*pOld != *pNew)
{
// Erases olde value
tft.setTextColor(COLOR_BLACK);
tft.setCursor(c, line);
tft.print(*pOld);
// Writes new value
tft.setTextColor(color);
tft.setCursor(c, line);
tft.print(*pNew);
}
pOld++;
pNew++;
c += space;
}
// Is there anything else to erase?
tft.setTextColor(COLOR_BLACK);
while (*pOld)
{
tft.setCursor(c, line);
tft.print(*pOld);
pOld++;
c += space;
}
// Is there anything else to print?
tft.setTextColor(color);
while (*pNew)
{
tft.setCursor(c, line);
tft.print(*pNew);
pNew++;
c += space;
}
// Save the current content to be tested next time
strcpy(oldValue, newValue);
}
/*
Shows frequency information on Display
*/
void showFrequency()
{
char freq[15];
char aux[15];
currentFrequency = rx.getFrequency();
// Serial.println(currentFrequency);
tft.setFont(&DSEG7_Classic_Mini_Regular_30);
tft.setTextSize(1);
if (band[bandIdx].mode == MODE_FM) // FM
{
sprintf(aux, "%6.6lu", currentFrequency);
freq[0] = aux[0];
freq[1] = aux[1];
freq[2] = aux[2];
freq[3] = '\0';
freq[4] = aux[3];
freq[5] = aux[4];
freq[6] = '\0';
printValue(2, 36, &oldFreq[0], &freq[0], 23, COLOR_RED);
printValue(82, 36, &oldFreq[4], &freq[4], 23, COLOR_RED);
tft.setCursor(80, 35);
tft.print('.');
}
else // AM
{
sprintf(aux, "%5lu", currentFrequency);
freq[0] = aux[0];
freq[1] = aux[1];
freq[2] = aux[2];
freq[3] = aux[3];
freq[4] = aux[4];
freq[5] = '\0';
printValue(2, 36, &oldFreq[0], &freq[0], 23, COLOR_RED);
}
}
/*
Show some basic information on display
*/
void showStatus()
{
resetBuffer();
clearStatus();
showFrequency();
showVolume();
showBandwidth();
}
/* *******************************
Shows RSSI status
*/
void showRSSI()
{
/*
char rssi[15];
// Check AM or FM
sprintf(rssi, "%3.3udBuV", (band[bandIdx].mode == MODE_FM)? rx.getFmRssi():rx.getAmRssi());
tft.setFont(&Serif_plain_14);
tft.setTextSize(1);
printValue(5, 55, oldRssi, rssi, 11, COLOR_WHITE);
*/
}
void showBandwidth()
{
char sBw[15];
if (band[bandIdx].mode != MODE_AM)
return;
sprintf(sBw, "%cKHz", am_bw[bwIdx]);
tft.setFont(&Serif_plain_14);
tft.setTextSize(1);
printValue(5, 80, oldBW, sBw, 11, COLOR_WHITE);
}
void showStereo()
{
// char stereo[10];
// sprintf(stereo, "%s", (rx.isFmStereo()) ? "St" : "Mo");
// tft.setFont(&Serif_plain_14);
// tft.setTextSize(1);
// printValue(125, 55, oldStereo, stereo, 15, COLOR_WHITE);
}
/*
Shows the volume level on LCD
*/
void showVolume()
{
// char sVolume[15];
// sprintf(sVolume, "Vol: %2.2u", rx.getVolume());
// printValue(80, 56, oldVolume, sVolume, 6, 1);
}
/*********************************************************
*********************************************************/
void showSplash()
{
// Splash
tft.setFont(&Serif_plain_14);
tft.setTextSize(1);
tft.setTextColor(COLOR_YELLOW);
tft.setCursor(45, 23);
tft.print("KT0915");
tft.setCursor(15, 50);
tft.print("Arduino Library");
tft.setCursor(25, 80);
tft.print("By PU2CLR");
tft.setFont(&Serif_plain_14);
tft.setTextSize(0);
tft.setCursor(12, 110);
tft.print("Ricardo L. Caratti");
delay(4000);
}
void bandUp()
{
// save the current frequency for the band
band[bandIdx].default_frequency = currentFrequency;
if (bandIdx < lastBand)
{
bandIdx++;
}
else
{
bandIdx = 0;
}
useBand();
}
void bandDown()
{
// save the current frequency for the band
band[bandIdx].default_frequency = currentFrequency;
if (bandIdx > 0)
{
bandIdx--;
}
else
{
bandIdx = lastBand;
}
useBand();
}
void useBand()
{
if (band[bandIdx].mode == MODE_FM)
{
rx.setFM(band[bandIdx].minimum_frequency, band[bandIdx].maximum_frequency, band[bandIdx].default_frequency, band[bandIdx].step);
rx.setDeEmphasis(DE_EMPHASIS_75);
// rx.setSoftMute(TURN_OFF);
rx.setFmAfc(TURN_ON);
rx.setMono(TURN_OFF); // Force stereo
}
else
{
rx.setAM(band[bandIdx].minimum_frequency, band[bandIdx].maximum_frequency, band[bandIdx].default_frequency, band[bandIdx].step);
rx.setAmAfc(TURN_ON);
rx.setSoftMute(TURN_OFF);
rx.setAmSpace(0); // Sets Am space channel to 1Khz.
}
delay(100);
currentFrequency = band[bandIdx].default_frequency;
rx.setFrequency(currentFrequency);
showStatus();
}
/**
* Used to test the receiver functions implemented by the library
*/
void doBandwidth()
{
if (bwIdx == 3)
bwIdx = 0;
bwIdx++;
rx.setAmBandwidth(bwIdx);
showBandwidth();
showFrequency();
delay(300);
}
void doStereo()
{
rx.setMono((bSt = !bSt));
bShow = true;
showStereo();
delay(100);
}
/**
Process seek command.
The seek direction is based on the last encoder direction rotation.
*/
void doSeek()
{
delay(200);
bShow = true;
showFrequency();
}
/*
Button - Volume control
*/
void volumeButton(byte d)
{
if (d == 1)
rx.setVolumeUp();
else
rx.setVolumeDown();
showVolume();
delay(MIN_ELAPSED_TIME); // waits a little more for releasing the button.
}
void doFilter()
{
}
void APP_loop()
{
// Check if the encoder has moved.
if (encoderCount != 0)
{
if (encoderCount == 1)
{
rx.setFrequencyUp();
}
else
{
rx.setFrequencyDown();
}
showFrequency();
bShow = true;
encoderCount = 0;
}
// Check button commands
if ((millis() - elapsedButton) > MIN_ELAPSED_TIME)
{
// check if some button is pressed
if (digitalRead(BAND_MODE_SWITCH_UP) == LOW)
bandUp();
else if (digitalRead(BAND_MODE_SWITCH_DOWN) == LOW)
bandDown();
else if (digitalRead(VOL_UP) == LOW)
volumeButton(1);
else if (digitalRead(VOL_DOWN) == LOW)
volumeButton(-1);
else if (digitalRead(SWITCH_BW) == LOW)
doBandwidth();
}
if ((millis() - pollin_elapsed) > POLLING_TIME)
{
showRSSI();
pollin_elapsed = millis();
}
delay(100);
}

0
Core/APP/app.h Normal file
View File

49
Core/Inc/gpio.h Normal file
View File

@ -0,0 +1,49 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.h
* @brief This file contains all the function prototypes for
* the gpio.c file
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_H__
#define __GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_GPIO_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ GPIO_H__ */

107
Core/Inc/main.h Normal file
View File

@ -0,0 +1,107 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32g0xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define ENCODER_KEY_Pin GPIO_PIN_13
#define ENCODER_KEY_GPIO_Port GPIOC
#define KEY_1_Pin GPIO_PIN_0
#define KEY_1_GPIO_Port GPIOA
#define KEY_2_Pin GPIO_PIN_1
#define KEY_2_GPIO_Port GPIOA
#define KEY_3_Pin GPIO_PIN_2
#define KEY_3_GPIO_Port GPIOA
#define KEY_4_Pin GPIO_PIN_3
#define KEY_4_GPIO_Port GPIOA
#define KEY_5_Pin GPIO_PIN_4
#define KEY_5_GPIO_Port GPIOA
#define LCD_BK_Pin GPIO_PIN_6
#define LCD_BK_GPIO_Port GPIOA
#define LED_2_Pin GPIO_PIN_8
#define LED_2_GPIO_Port GPIOA
#define ENCODER_A_Pin GPIO_PIN_6
#define ENCODER_A_GPIO_Port GPIOC
#define ENCODER_B_Pin GPIO_PIN_7
#define ENCODER_B_GPIO_Port GPIOC
#define LED_3_Pin GPIO_PIN_11
#define LED_3_GPIO_Port GPIOA
#define LED_4_Pin GPIO_PIN_12
#define LED_4_GPIO_Port GPIOA
#define LED_STATUS_Pin GPIO_PIN_15
#define LED_STATUS_GPIO_Port GPIOA
#define LCD_RST_Pin GPIO_PIN_0
#define LCD_RST_GPIO_Port GPIOD
#define KEY_6_Pin GPIO_PIN_1
#define KEY_6_GPIO_Port GPIOD
#define LCD_DC_Pin GPIO_PIN_2
#define LCD_DC_GPIO_Port GPIOD
#define LED_1_Pin GPIO_PIN_3
#define LED_1_GPIO_Port GPIOD
#define SWI2C_SCL_Pin GPIO_PIN_3
#define SWI2C_SCL_GPIO_Port GPIOB
#define SWI2C_SDA_Pin GPIO_PIN_4
#define SWI2C_SDA_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */

52
Core/Inc/spi.h Normal file
View File

@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file spi.h
* @brief This file contains all the function prototypes for
* the spi.c file
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SPI_H__
#define __SPI_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern SPI_HandleTypeDef hspi1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_SPI1_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __SPI_H__ */

View File

@ -0,0 +1,351 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32g0xx_hal_conf.h
* @author MCD Application Team
* @brief HAL configuration file.
******************************************************************************
* @attention
*
* Copyright (c) 2018 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32G0xx_HAL_CONF_H
#define STM32G0xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/* #define HAL_ADC_MODULE_ENABLED */
/* #define HAL_CEC_MODULE_ENABLED */
/* #define HAL_COMP_MODULE_ENABLED */
/* #define HAL_CRC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_DAC_MODULE_ENABLED */
/* #define HAL_EXTI_MODULE_ENABLED */
/* #define HAL_FDCAN_MODULE_ENABLED */
/* #define HAL_HCD_MODULE_ENABLED */
/* #define HAL_I2C_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_LPTIM_MODULE_ENABLED */
/* #define HAL_PCD_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */
/* #define HAL_RTC_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */
/* #define HAL_SMBUS_MODULE_ENABLED */
#define HAL_SPI_MODULE_ENABLED
#define HAL_TIM_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_WWDG_MODULE_ENABLED */
#define HAL_GPIO_MODULE_ENABLED
#define HAL_EXTI_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
/* ########################## Register Callbacks selection ############################## */
/**
* @brief This is the list of modules where register callback can be used
*/
#define USE_HAL_ADC_REGISTER_CALLBACKS 0u
#define USE_HAL_CEC_REGISTER_CALLBACKS 0u
#define USE_HAL_COMP_REGISTER_CALLBACKS 0u
#define USE_HAL_CRYP_REGISTER_CALLBACKS 0u
#define USE_HAL_DAC_REGISTER_CALLBACKS 0u
#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0u
#define USE_HAL_HCD_REGISTER_CALLBACKS 0u
#define USE_HAL_I2C_REGISTER_CALLBACKS 0u
#define USE_HAL_I2S_REGISTER_CALLBACKS 0u
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0u
#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0u
#define USE_HAL_PCD_REGISTER_CALLBACKS 0u
#define USE_HAL_RNG_REGISTER_CALLBACKS 0u
#define USE_HAL_RTC_REGISTER_CALLBACKS 0u
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0u
#define USE_HAL_SPI_REGISTER_CALLBACKS 0u
#define USE_HAL_TIM_REGISTER_CALLBACKS 0u
#define USE_HAL_UART_REGISTER_CALLBACKS 0u
#define USE_HAL_USART_REGISTER_CALLBACKS 0u
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0u
/* ########################## Oscillator Values adaptation ####################*/
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE (8000000UL) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT (100UL) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
#if defined(STM32G0C1xx) || defined(STM32G0B1xx) || defined(STM32G0B0xx)
/**
* @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG.
* This internal oscillator is mainly dedicated to provide a high precision clock to
* the USB peripheral by means of a special Clock Recovery System (CRS) circuitry.
* When the CRS is not used, the HSI48 RC oscillator runs on it default frequency
* which is subject to manufacturing process variations.
*/
#if !defined (HSI48_VALUE)
#define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz.
The real value my vary depending on manufacturing process variations.*/
#endif /* HSI48_VALUE */
#endif
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#define LSI_VALUE (32000UL) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief External Low Speed oscillator (LSE) value.
* This value is used by the UART, RTC HAL module to compute the system frequency
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE (32768UL) /*!< Value of the External oscillator in Hz*/
#endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT (5000UL) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for I2S1 peripheral
* This value is used by the RCC HAL module to compute the I2S1 clock source
* frequency.
*/
#if !defined (EXTERNAL_I2S1_CLOCK_VALUE)
#define EXTERNAL_I2S1_CLOCK_VALUE (12288000UL) /*!< Value of the I2S1 External clock source in Hz*/
#endif /* EXTERNAL_I2S1_CLOCK_VALUE */
#if defined(STM32G0C1xx) || defined(STM32G0B1xx) || defined(STM32G0B0xx)
/**
* @brief External clock source for I2S2 peripheral
* This value is used by the RCC HAL module to compute the I2S2 clock source
* frequency.
*/
#if !defined (EXTERNAL_I2S2_CLOCK_VALUE)
#define EXTERNAL_I2S2_CLOCK_VALUE 48000U /*!< Value of the I2S2 External clock source in Hz*/
#endif /* EXTERNAL_I2S2_CLOCK_VALUE */
#endif
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE (3300UL) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY 3U /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U
/* ################## SPI peripheral configuration ########################## */
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
* Activated: CRC code is present inside driver
* Deactivated: CRC code cleaned from driver
*/
#define USE_SPI_CRC 0U
/* ################## CRYP peripheral configuration ########################## */
#define USE_HAL_CRYP_SUSPEND_RESUME 1U
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1U */
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include modules header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32g0xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32g0xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32g0xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32g0xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32g0xx_hal_adc.h"
#include "stm32g0xx_hal_adc_ex.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_CEC_MODULE_ENABLED
#include "stm32g0xx_hal_cec.h"
#endif /* HAL_CEC_MODULE_ENABLED */
#ifdef HAL_COMP_MODULE_ENABLED
#include "stm32g0xx_hal_comp.h"
#endif /* HAL_COMP_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32g0xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_CRYP_MODULE_ENABLED
#include "stm32g0xx_hal_cryp.h"
#endif /* HAL_CRYP_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED
#include "stm32g0xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_EXTI_MODULE_ENABLED
#include "stm32g0xx_hal_exti.h"
#endif /* HAL_EXTI_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32g0xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_FDCAN_MODULE_ENABLED
#include "stm32g0xx_hal_fdcan.h"
#endif /* HAL_FDCAN_MODULE_ENABLED */
#ifdef HAL_HCD_MODULE_ENABLED
#include "stm32g0xx_hal_hcd.h"
#endif /* HAL_HCD_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32g0xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED
#include "stm32g0xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32g0xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32g0xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_LPTIM_MODULE_ENABLED
#include "stm32g0xx_hal_lptim.h"
#endif /* HAL_LPTIM_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32g0xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32g0xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_RNG_MODULE_ENABLED
#include "stm32g0xx_hal_rng.h"
#endif /* HAL_RNG_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32g0xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32g0xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_SMBUS_MODULE_ENABLED
#include "stm32g0xx_hal_smbus.h"
#endif /* HAL_SMBUS_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32g0xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32g0xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32g0xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32g0xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32g0xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for functions parameters check.
* @param expr If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t *file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* STM32G0xx_HAL_CONF_H */

62
Core/Inc/stm32g0xx_it.h Normal file
View File

@ -0,0 +1,62 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32g0xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32G0xx_IT_H
#define __STM32G0xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void SVC_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32G0xx_IT_H */

52
Core/Inc/tim.h Normal file
View File

@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.h
* @brief This file contains all the function prototypes for
* the tim.c file
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIM_H__
#define __TIM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern TIM_HandleTypeDef htim3;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_TIM3_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __TIM_H__ */

52
Core/Inc/usart.h Normal file
View File

@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.h
* @brief This file contains all the function prototypes for
* the usart.c file
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */

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 "main.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,53 @@
#pragma once
#include <stdint.h>
const uint8_t IMG_DIGI_18_32[] = {
0xB3, 0x1F, 0x00, 0xFC, 0xFA, 0xF6, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E,
0xF6, 0xFA, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0xF8, 0xFC, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E,
0x0E, 0x0E, 0x0E, 0x0E, 0xF6, 0xFA, 0xFC, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0E, 0x0E, 0x0E, 0x0E,
0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0xF6, 0xFA, 0xFC, 0x00, 0x00, 0xFC, 0xF8, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF8, 0xFC, 0x00, 0x00, 0xFC, 0xFA, 0xF6,
0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0xFC,
0xFA, 0xF6, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x06, 0x02, 0x00, 0x00,
0x00, 0x00, 0x02, 0x06, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0xF6, 0xFA,
0xFC, 0x00, 0x00, 0xFC, 0xFA, 0xF6, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E,
0xF6, 0xFA, 0xFC, 0x00, 0x00, 0xFC, 0xFA, 0xF6, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E,
0x0E, 0x0E, 0xF6, 0xFA, 0xFC, 0x00, 0x00, 0xFF, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xBF, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xBF, 0x7F, 0xFF, 0x00, 0x00, 0xFF,
0x7F, 0xBF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xBF, 0x7F, 0xFF, 0x00,
0x00, 0xFF, 0x7F, 0xBF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
0x00, 0x00, 0x00, 0xFF, 0x7F, 0xBF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3F, 0x7F, 0xFF, 0x00, 0x00, 0xFF, 0x7F, 0xBF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0xBF, 0x7F, 0xFF, 0x00, 0x00, 0xFF, 0x7F, 0xBF, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xBF, 0x7F, 0xFF, 0x00, 0x00, 0xFE, 0xFC, 0xF8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFC, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFC, 0xFE, 0x00, 0x00, 0xFE,
0xFD, 0xFB, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFB, 0xFD,
0xFE, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0xFB, 0xFD, 0xFE, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0xFB, 0xFD, 0xFE, 0x00, 0x00, 0xFE, 0xFD, 0xFB, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0xFB, 0xFD, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFC, 0xFE, 0x00, 0x00, 0xFE, 0xFD, 0xFB, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFB, 0xFD, 0xFE, 0x00, 0x00, 0x00, 0x01, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFB, 0xFD, 0xFE, 0x00, 0x00, 0x7F,
0xBF, 0xDF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xDF, 0xBF, 0x7F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3F,
0x7F, 0x00, 0x00, 0x7F, 0xBF, 0xDF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xDF, 0xBF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x7F, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xDF, 0xBF, 0x7F, 0x00, 0x00, 0x7F, 0xBF, 0xDF, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xDF, 0xBF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x7F, 0x00, 0x00, 0x7F,
0xBF, 0xDF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xDF, 0xBF, 0x7F, 0x00,
0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xDF, 0xBF,
0x7F, 0x00,
};
const uint32_t DATA_SIZE_DIGI_18_32 = 722;

52
Core/ST7735/UI/monoimg.c Normal file
View File

@ -0,0 +1,52 @@
#include <stdint.h>
#include "monoimg.h"
#define max(a,b) ((a) >= (b) ? (a) : (b))
#define min(a,b) ((a) <= (b) ? (a) : (b))
uint8_t mimg_get_pixel_unsafe(const uint8_t *img, uint8_t x, uint8_t y) {
// MVLSB format
uint8_t width = img[0] + 1;
uint16_t index = (y >> 3) * width + x + 2;
uint8_t offset = y & 0x07;
uint8_t value = (img[index] >> offset) & 0x01;
return value; // return 1 or 0
}
uint8_t mimg_get_pixel(const uint8_t *img, uint16_t x, uint16_t y) {
// MVLSB format
uint8_t width = img[0] + 1;
uint8_t height = img[1] + 1;
if (x >= width || y >= height) {
return 0;
}
return mimg_get_pixel_unsafe(img, (uint8_t)x, (uint8_t)y);
}
void mimg_draw(mimg_FunctionSetPixel set_pixel, uint16_t x, uint16_t y, uint16_t color, const uint8_t *img, mimg_Area area) {
uint8_t width_s1 = img[0]; // width - 1
uint8_t height_s1 = img[1]; // height - 1
uint8_t ix = min(area.x, width_s1);
uint8_t iy = min(area.y, height_s1);
uint8_t iw = min(area.w, width_s1 - ix + 1);
uint8_t ih = min(area.h, height_s1 - iy + 1);
uint8_t off_x, off_y;
for (off_y = 0; off_y < ih; off_y ++) {
for (off_x = 0; off_x < iw; off_x ++) {
if (mimg_get_pixel_unsafe(img, ix + off_x, iy + off_y)) {
set_pixel(x + off_x, y + off_y, color);
}
}
}
}
mimg_Area mimg_get_tile_area(const uint8_t *img, uint8_t cols, uint8_t rows, uint8_t index) {
uint8_t width = img[0] + 1;
uint8_t height = img[1] + 1;
mimg_Area area;
area.w = width / cols;
area.h = height / rows;
area.y = (index / cols) * area.h;
area.x = (index % cols) * area.w;
return area;
}

19
Core/ST7735/UI/monoimg.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
typedef void (*mimg_FunctionSetPixel)(uint16_t x, uint16_t y, uint16_t color);
typedef struct mimg_Area
{
uint8_t x;
uint8_t y;
uint8_t w;
uint8_t h;
} mimg_Area;
/** get a pixel from img, return 1 or 0 */
uint8_t mimg_get_pixel(const uint8_t *img, uint16_t x, uint16_t y);
/** draw a part of img {ix, iy, iw, ih} , at (x, y) with color */
void mimg_draw(mimg_FunctionSetPixel set_pixel, uint16_t x, uint16_t y, uint16_t color, const uint8_t *img, mimg_Area area);
/** calc tile area */
mimg_Area mimg_get_tile_area(const uint8_t *img, uint8_t cols, uint8_t rows, uint8_t index);

26
Core/ST7735/UI/ui.c Normal file
View File

@ -0,0 +1,26 @@
#include <stdint.h>
#include "Images/digi18x32.h"
#include "monoimg.h"
#include "st7735.h"
void ui_text_number18x32(uint32_t num, uint16_t x, uint16_t y, uint16_t color) {
uint32_t tmp = num;
uint32_t div = 1;
uint8_t num_count = 0;
while (tmp > 0) {
tmp = tmp / 10;
num_count ++;
div = div * 10;
}
div = div / 10;
while (div > 0) {
tmp = (num / div) % 10;
printf("div: %d x: %d tmp: %d\n", div, x, tmp);
mimg_Area area = mimg_get_tile_area(IMG_DIGI_18_32, 10, 1, tmp);
mimg_draw(ST7735_DrawPixel, x, y, color, IMG_DIGI_18_32, area);
x = x + 18;
div = div / 10;
}
}
// TODO: 绘制文字的方法

4
Core/ST7735/UI/ui.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
#include <stdint.h>
void ui_text_number18x32(uint32_t num, uint16_t x, uint16_t y, uint16_t color);

283
Core/ST7735/st7735.c Normal file
View File

@ -0,0 +1,283 @@
/* vim: set ai et ts=4 sw=4: */
#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));
// write to RAM
ST7735_WriteCommand(ST7735_RAMWR);
}
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);
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);
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_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();
}

247
Core/ST7735/st7735.h Normal file
View File

@ -0,0 +1,247 @@
/* vim: set ai et ts=4 sw=4: */
#ifndef __ST7735_H__
#define __ST7735_H__
#include <stdbool.h>
#include <stdlib.h>
#include "main.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__

764
Core/SWI2C/i2c_sw.c Normal file
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);
}

54
Core/SWI2C/i2c_sw.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef __I2C_SW_H
#define __I2C_SW_H
/* includes */
#include "main.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 */

43
Core/SWI2C/readme.md Normal file
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);
}
}
```

111
Core/Src/gpio.c Normal file
View File

@ -0,0 +1,111 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.c
* @brief This file provides code for the configuration
* of all used GPIO pins.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure GPIO */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, LCD_BK_Pin|LED_2_Pin|LED_3_Pin|LED_4_Pin
|LED_STATUS_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, LCD_RST_Pin|LCD_DC_Pin|LED_1_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, SWI2C_SCL_Pin|SWI2C_SDA_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = ENCODER_KEY_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(ENCODER_KEY_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PAPin PAPin PAPin PAPin
PAPin */
GPIO_InitStruct.Pin = KEY_1_Pin|KEY_2_Pin|KEY_3_Pin|KEY_4_Pin
|KEY_5_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PAPin PAPin PAPin PAPin
PAPin */
GPIO_InitStruct.Pin = LCD_BK_Pin|LED_2_Pin|LED_3_Pin|LED_4_Pin
|LED_STATUS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PDPin PDPin PDPin */
GPIO_InitStruct.Pin = LCD_RST_Pin|LCD_DC_Pin|LED_1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = KEY_6_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(KEY_6_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PBPin PBPin */
GPIO_InitStruct.Pin = SWI2C_SCL_Pin|SWI2C_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */

216
Core/Src/main.c Normal file
View File

@ -0,0 +1,216 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "RotaryCoder.h"
#include "st7735.h"
#include "ui.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
#ifdef __GNUC__
int _write(int fd, char *ptr, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, 0xFFFF);
return len;
}
#endif
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void LCD_init()
{
ST7735_Init(); // 屏幕初始化
HAL_GPIO_WritePin(LCD_BK_GPIO_Port, LCD_BK_Pin, GPIO_PIN_SET);
//const char ready[] = "Init Ready!\r\n";
//HAL_UART_Transmit(&huart1, (uint8_t *)ready, sizeof(ready) - 1, HAL_MAX_DELAY);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_SPI1_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
/*EC11_init();
uint16_t Count;
uint16_t Diretion;*/
printf("program start\n");
LCD_init();
ST7735_FillScreen(ST7735_WHITE);
printf("Begin draw number\n");
ui_text_number18x32(10086, 0, 0, 0xFF00);
printf("End draw number\n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(LED_STATUS_GPIO_Port,LED_STATUS_Pin);
HAL_Delay(300);
/*
Count = EC11_COUNT();
Diretion = EC11_DIR();
printf("DIRE:%d COUNT:%d \r\n",Diretion,Count);
HAL_Delay(500);
*/
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 16;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

119
Core/Src/spi.c Normal file
View File

@ -0,0 +1,119 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file spi.c
* @brief This file provides code for the configuration
* of the SPI instances.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "spi.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
SPI_HandleTypeDef hspi1;
/* SPI1 init function */
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* SPI1 clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
if(spiHandle->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspDeInit 0 */
/* USER CODE END SPI1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI1_CLK_DISABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA7 ------> SPI1_MOSI
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_7);
/* USER CODE BEGIN SPI1_MspDeInit 1 */
/* USER CODE END SPI1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@ -0,0 +1,81 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32g0xx_hal_msp.c
* @brief This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
/* USER CODE END Define */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */
/* USER CODE END Macro */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */
/* USER CODE END ExternalFunctions */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
/* System interrupt init*/
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

145
Core/Src/stm32g0xx_it.c Normal file
View File

@ -0,0 +1,145 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32g0xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32g0xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M0+ Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVC_IRQn 0 */
/* USER CODE END SVC_IRQn 0 */
/* USER CODE BEGIN SVC_IRQn 1 */
/* USER CODE END SVC_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32G0xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32g0xx.s). */
/******************************************************************************/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

302
Core/Src/system_stm32g0xx.c Normal file
View File

@ -0,0 +1,302 @@
/**
******************************************************************************
* @file system_stm32g0xx.c
* @author MCD Application Team
* @brief CMSIS Cortex-M0+ Device Peripheral Access Layer System Source File
*
* This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32g0xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
* After each device reset the HSI (8 MHz then 16 MHz) is used as system clock source.
* Then SystemInit() function is called, in "startup_stm32g0xx.s" file, to
* configure the system clock before to branch to main program.
*
* This file configures the system clock as follows:
*=============================================================================
*-----------------------------------------------------------------------------
* System Clock source | HSI
*-----------------------------------------------------------------------------
* SYSCLK(Hz) | 16000000
*-----------------------------------------------------------------------------
* HCLK(Hz) | 16000000
*-----------------------------------------------------------------------------
* AHB Prescaler | 1
*-----------------------------------------------------------------------------
* APB Prescaler | 1
*-----------------------------------------------------------------------------
* HSI Division factor | 1
*-----------------------------------------------------------------------------
* PLL_M | 1
*-----------------------------------------------------------------------------
* PLL_N | 8
*-----------------------------------------------------------------------------
* PLL_P | 7
*-----------------------------------------------------------------------------
* PLL_Q | 2
*-----------------------------------------------------------------------------
* PLL_R | 2
*-----------------------------------------------------------------------------
* Require 48MHz for RNG | Disabled
*-----------------------------------------------------------------------------
*=============================================================================
******************************************************************************
* @attention
*
* Copyright (c) 2018-2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32g0xx_system
* @{
*/
/** @addtogroup STM32G0xx_System_Private_Includes
* @{
*/
#include "stm32g0xx.h"
#if !defined (HSE_VALUE)
#define HSE_VALUE (8000000UL) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
#if !defined (LSI_VALUE)
#define LSI_VALUE (32000UL) /*!< Value of LSI in Hz*/
#endif /* LSI_VALUE */
#if !defined (LSE_VALUE)
#define LSE_VALUE (32768UL) /*!< Value of LSE in Hz*/
#endif /* LSE_VALUE */
/**
* @}
*/
/** @addtogroup STM32G0xx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32G0xx_System_Private_Defines
* @{
*/
/************************* Miscellaneous Configuration ************************/
/* Note: Following vector table addresses must be defined in line with linker
configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
anywhere in Flash or Sram, else the vector table is kept at the automatic
remap of boot address selected */
/* #define USER_VECT_TAB_ADDRESS */
#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32G0xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32G0xx_System_Private_Variables
* @{
*/
/* The SystemCoreClock variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the 2 first functions listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = 16000000UL;
const uint32_t AHBPrescTable[16UL] = {0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 1UL, 2UL, 3UL, 4UL, 6UL, 7UL, 8UL, 9UL};
const uint32_t APBPrescTable[8UL] = {0UL, 0UL, 0UL, 0UL, 1UL, 2UL, 3UL, 4UL};
/**
* @}
*/
/** @addtogroup STM32G0xx_System_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @addtogroup STM32G0xx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system.
* @param None
* @retval None
*/
void SystemInit(void)
{
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation */
#endif /* USER_VECT_TAB_ADDRESS */
}
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock (HCLK), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock (HCLK) changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**) / HSI division factor
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
*
* - If SYSCLK source is LSI, SystemCoreClock will contain the LSI_VALUE
*
* - If SYSCLK source is LSE, SystemCoreClock will contain the LSE_VALUE
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***)
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
*
* (**) HSI_VALUE is a constant defined in stm32g0xx_hal_conf.h file (default value
* 16 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (***) HSE_VALUE is a constant defined in stm32g0xx_hal_conf.h file (default value
* 8 MHz), user has to ensure that HSE_VALUE is same as the real
* frequency of the crystal used. Otherwise, this function may
* have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
*
* @param None
* @retval None
*/
void SystemCoreClockUpdate(void)
{
uint32_t tmp;
uint32_t pllvco;
uint32_t pllr;
uint32_t pllsource;
uint32_t pllm;
uint32_t hsidiv;
/* Get SYSCLK source -------------------------------------------------------*/
switch (RCC->CFGR & RCC_CFGR_SWS)
{
case RCC_CFGR_SWS_0: /* HSE used as system clock */
SystemCoreClock = HSE_VALUE;
break;
case (RCC_CFGR_SWS_1 | RCC_CFGR_SWS_0): /* LSI used as system clock */
SystemCoreClock = LSI_VALUE;
break;
case RCC_CFGR_SWS_2: /* LSE used as system clock */
SystemCoreClock = LSE_VALUE;
break;
case RCC_CFGR_SWS_1: /* PLL used as system clock */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
SYSCLK = PLL_VCO / PLLR
*/
pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1UL;
if(pllsource == 0x03UL) /* HSE used as PLL clock source */
{
pllvco = (HSE_VALUE / pllm);
}
else /* HSI used as PLL clock source */
{
pllvco = (HSI_VALUE / pllm);
}
pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1UL);
SystemCoreClock = pllvco/pllr;
break;
case 0x00000000U: /* HSI used as system clock */
default: /* HSI used as system clock */
hsidiv = (1UL << ((READ_BIT(RCC->CR, RCC_CR_HSIDIV))>> RCC_CR_HSIDIV_Pos));
SystemCoreClock = (HSI_VALUE/hsidiv);
break;
}
/* Compute HCLK clock frequency --------------------------------------------*/
/* Get HCLK prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
/* HCLK clock frequency */
SystemCoreClock >>= tmp;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/

141
Core/Src/tim.c Normal file
View File

@ -0,0 +1,141 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.c
* @brief This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"
/* USER CODE BEGIN 0 */
#include "usart.h"
/* USER CODE END 0 */
TIM_HandleTypeDef htim3;
/* TIM3 init function */
void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 255;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
sConfig.IC1Polarity = TIM_ICPOLARITY_FALLING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
}
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(tim_encoderHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**TIM3 GPIO Configuration
PC6 ------> TIM3_CH1
PC7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = ENCODER_A_Pin|ENCODER_B_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
}
void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)
{
if(tim_encoderHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/**TIM3 GPIO Configuration
PC6 ------> TIM3_CH1
PC7 ------> TIM3_CH2
*/
HAL_GPIO_DeInit(GPIOC, ENCODER_A_Pin|ENCODER_B_Pin);
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/*
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance->CR1==0x01)//顺时针
//Rotary=1;
HAL_UART_Transmit(&huart1,"CW\r\n",10,1000);
HAL_TIM_Encoder_Stop_IT(&htim3,TIM_CHANNEL_ALL);
if(htim->Instance->CR1==0x11)//逆时针
//Rotary=0;
HAL_UART_Transmit(&huart1,"ccw\r\n",10,1000);
HAL_TIM_Encoder_Stop_IT(&htim3,TIM_CHANNEL_ALL);
}
*/
/* USER CODE END 1 */

140
Core/Src/usart.c Normal file
View File

@ -0,0 +1,140 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
#include <stdio.h>
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/** Initializes the peripherals clocks
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

810
Core/kt0915/KT0915.C Normal file
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
}

582
Core/kt0915/KT0915.h Normal file
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 "main.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);