commit 0f7b02c8a663ee0027e2c1a56ecafbe50ce015c7 Author: Puck Meerburg Date: Tue Dec 30 13:48:35 2025 +0000 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build diff --git a/CH5xx_ble_firmware_library/BLE/CH58xBLE_LIB.h b/CH5xx_ble_firmware_library/BLE/CH58xBLE_LIB.h new file mode 100644 index 0000000..0142f8d --- /dev/null +++ b/CH5xx_ble_firmware_library/BLE/CH58xBLE_LIB.h @@ -0,0 +1,4594 @@ +/********************************** (C) COPYRIGHT ****************************** + * File Name : CH58xBLE_LIB.H + * Author : WCH + * Version : V1.70 + * Date : 2023/01/10 + * Description : head file + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + *******************************************************************************/ + + +/******************************************************************************/ +#ifndef __CH58xBLE_LIB_H +#define __CH58xBLE_LIB_H + +#ifdef __cplusplus +extern "C" +{ +#endif +#include "stdint.h" + +#ifndef int8 +typedef int8_t int8; +#endif +#ifndef int16 +typedef int16_t int16; +#endif +#ifndef BOOL +typedef uint8_t BOOL; +#endif +#ifndef s8 +typedef int8_t s8; +#endif +#ifndef s16 +typedef int16_t s16; +#endif +#ifndef s32 +typedef int32_t s32; +#endif +#ifndef u8 +typedef uint8_t u8; +#endif +#ifndef u16 +typedef uint16_t u16; +#endif +#ifndef u32 +typedef uint32_t u32; +#endif +#ifndef u64 +typedef uint64_t u64; +#endif +#ifndef u8C +typedef const uint8_t u8C; +#endif + +#ifndef u8V +typedef uint8_t volatile u8V; +#endif +#ifndef u32V +typedef uint32_t volatile u32V; +#endif + +#ifndef uint8 +typedef uint8_t uint8; +#endif +#ifndef uint16 +typedef uint16_t uint16; +#endif +#ifndef uint32 +typedef uint32_t uint32; +#endif + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif +#ifndef NULL + #define NULL 0 +#endif +#ifndef SUCCESS +#define SUCCESS 0x00 +#endif +#ifndef bStatus_t +typedef uint8_t bStatus_t; +#endif +#ifndef tmosTaskID +typedef uint8_t tmosTaskID; +#endif +#ifndef tmosEvents +typedef uint16_t tmosEvents; +#endif +#ifndef tmosTimer +typedef uint32_t tmosTimer; +#endif +#ifndef tmosSnvId_t +typedef uint8_t tmosSnvId_t; +#endif +#ifndef tmosSnvLen_t +typedef uint8_t tmosSnvLen_t; +#endif + +// Define function type that generate a random seed callback +typedef uint32_t (*pfnSrandCB)( void ); +// Define function type that switch to idle mode callback +typedef uint32_t (*pfnIdleCB)( uint32_t ); +// Define function type that run LSI clock calibration callback +typedef void (*pfnLSICalibrationCB)( void ); +// Define function type that get temperature callback +typedef uint16_t (*pfnTempSampleCB)( void ); +// Define function type that connect/advertise event complete callback. +typedef void (*pfnEventCB)( uint32_t timeUs ); +// Define function type that library status callback. +typedef void (*pfnLibStatusErrorCB)( uint8_t code, uint32_t status ); +// Define function type that process event +typedef tmosEvents (*pTaskEventHandlerFn)( tmosTaskID taskID, tmosEvents event ); +// Define function type that read flash +typedef uint32_t (*pfnFlashReadCB)( uint32_t addr, uint32_t num, uint32_t *pBuf ); +// Define function type that write flash +typedef uint32_t (*pfnFlashWriteCB)( uint32_t addr, uint32_t num, uint32_t *pBuf ); +// Define function type that get system clock count +typedef uint32_t (*pfnGetSysClock)( void ); + +/* BLE library config struct */ +typedef struct tag_ble_config +{ + uint32_t MEMAddr; // library memory start address + uint16_t MEMLen; // library memory size + uint32_t SNVAddr; // SNV flash start address( if NULL,bonding information will not be saved ) + uint16_t SNVBlock; // SNV flash block size ( default 256 ) + uint8_t SNVNum; // SNV flash block number ( default 1 ) + uint8_t BufNumber; // Maximum number of sent and received packages cached by the controller( default 5 ) + // Must be greater than the number of connections. + uint16_t BufMaxLen; // Maximum length (in octets) of the data portion of each HCI data packet( default 27 ) + // SC enable,must be greater than 69 + // ATT_MTU = BufMaxLen-4,Range[23,ATT_MAX_MTU_SIZE] + uint8_t TxNumEvent; // Maximum number of TX data in a connection event ( default 1 ) + uint8_t RxNumEvent; // Maximum number of RX data in a connection event ( default equal to BufNumber ) + uint8_t TxPower; // Transmit power level( default LL_TX_POWEER_0_DBM(0dBm) ) + uint8_t WakeUpTime; // Wake up time value in one system count + uint8_t SelRTCClock; // system clock select + // bit0-1 00: LSE(32768Hz) 01:LSI(32000Hz) 10:LSI(32768Hz) + // bit7: 1: ble timer(HSE)(must disable sleep) + uint8_t ConnectNumber; // Connect number,lower two bits are peripheral number,followed by central number + uint8_t WindowWidening; // Wait rf start window(us) + uint8_t WaitWindow; // Wait event arrive window in one system clock + uint8_t MacAddr[6]; // MAC address,little-endian + pfnSrandCB srandCB; // Register a program that generate a random seed + pfnIdleCB sleepCB; // Register a program that set idle + pfnTempSampleCB tsCB; // Register a program that read the current temperature,determine whether calibration is need + pfnLSICalibrationCB rcCB; // Register a program that LSI clock calibration + pfnLibStatusErrorCB staCB; // Register a program that library status callback + pfnFlashReadCB readFlashCB; // Register a program that read flash + pfnFlashWriteCB writeFlashCB; // Register a program that write flash +} bleConfig_t; // Library initialization call BLE_LibInit function + +/* BLE pa control config struct */ +typedef struct tag_ble_pa_control_config +{ + uint32_t txEnableGPIO; // tx enable gpio register + uint32_t txDisableGPIO; // tx disable gpio register + uint32_t tx_pin; // tx pin define + uint32_t rxEnableGPIO; // rx enable gpio register + uint32_t rxDisableGPIO; // rx disable gpio register + uint32_t rx_pin; // tx pin define +} blePaControlConfig_t; + +// defined for all task +#define SYS_EVENT_MSG (0x8000) // A message is waiting event +#define INVALID_TASK_ID 0xFF // Task ID isn't setup properly +#define TASK_NO_TASK 0xFF + +typedef struct +{ + uint8_t event; + uint8_t status; +} tmos_event_hdr_t; + +/********************************************************************* + * GLOBAL MACROS + */ +#define VER_FILE "CH58x_BLE_LIB_V1.7" +extern const uint8_t VER_LIB[]; // LIB version +#define SYSTEM_TIME_MICROSEN 625 // unit of process event timer is 625us +#define MS1_TO_SYSTEM_TIME(x) ((x)*1000/SYSTEM_TIME_MICROSEN) // transform unit in ms to unit in 625us ( attentional bias ) +#define TMOS_TIME_VALID (30*1000*1000) // the maximum task time = RTC MAX clock - TMOS_TIME_VALID + +/* takes a byte out of a uint32_t : var - uint32_t, ByteNum - byte to take out (0 - 3) */ +#define BREAK_UINT32( var, ByteNum ) (uint8_t)((uint32_t)(((var) >>((ByteNum) * 8)) & 0x00FF)) +#define HI_UINT16(a) (((a) >> 8) & 0xFF) +#define LO_UINT16(a) ((a) & 0xFF) +#define HI_UINT8(a) (((a) >> 4) & 0x0F) +#define LO_UINT8(a) ((a) & 0x0F) +#define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \ + ((uint32_t)(((uint32_t)(Byte0) & 0x00FF) \ + + (((uint32_t)(Byte1) & 0x00FF) << 8) \ + + (((uint32_t)(Byte2) & 0x00FF) << 16) \ + + (((uint32_t)(Byte3) & 0x00FF) << 24))) +#define BUILD_UINT16(loByte, hiByte) ((uint16_t)(((loByte) & 0x00FF)|(((hiByte) & 0x00FF)<<8))) + +#define ACTIVE_LOW ! +#define ACTIVE_HIGH !! // double negation forces result to be '1' + +#ifndef BV +#define BV(n) (1 << (n)) +#endif + +#ifndef BF +#define BF(x,b,s) (((x) & (b)) >> (s)) +#endif + +#ifndef MIN +#define MIN(n,m) (((n) < (m)) ? (n) : (m)) +#endif + +#ifndef MAX +#define MAX(n,m) (((n) < (m)) ? (m) : (n)) +#endif + +#ifndef ABS +#define ABS(n) (((n) < 0) ? -(n) : (n)) +#endif + +/* TxPower define(Accuracy:��2dBm) */ +#define LL_TX_POWEER_MINUS_16_DBM 0x01 +#define LL_TX_POWEER_MINUS_12_DBM 0x02 +#define LL_TX_POWEER_MINUS_8_DBM 0x04 +#define LL_TX_POWEER_MINUS_5_DBM 0x07 +#define LL_TX_POWEER_MINUS_3_DBM 0x09 +#define LL_TX_POWEER_MINUS_1_DBM 0x0B +#define LL_TX_POWEER_0_DBM 0x0D +#define LL_TX_POWEER_1_DBM 0x0F +#define LL_TX_POWEER_2_DBM 0x13 +#define LL_TX_POWEER_3_DBM 0x17 +#define LL_TX_POWEER_4_DBM 0x1D +#define LL_TX_POWEER_5_DBM 0x29 +#define LL_TX_POWEER_6_DBM 0x3D + +/* ERR_LIB_INIT define */ +#define ERR_LLE_IRQ_HANDLE 0x01 +#define ERR_MEM_ALLOCATE_SIZE 0x02 +#define ERR_SET_MAC_ADDR 0x03 +#define ERR_GAP_ROLE_CONFIG 0x04 +#define ERR_CONNECT_NUMBER_CONFIG 0x05 +#define ERR_SNV_ADDR_CONFIG 0x06 +#define ERR_CLOCK_SELECT_CONFIG 0x07 + +//! Default Public and Random Address Length +#define B_ADDR_LEN 6 +//! Random Number Size +#define B_RANDOM_NUM_SIZE 8 +//! Default key length +#define KEYLEN 16 +#define PUBLIC_KEY_LEN 64 + +//! Maximum Advertising Packet Length +#define B_MAX_ADV_LEN 31 // maximum legacy advertising packet length +#define B_MAX_ADV_EXT_LEN 460 // maximum extended advertising packet length +#define B_MAX_ADV_PERIODIC_LEN 460 // maximum periodic advertising packet length + +#define FAILURE 0x01 //!< Failure +#define INVALIDPARAMETER 0x02 //!< Invalid request field +#define INVALID_TASK 0x03 //!< Task ID isn't setup properly +#define MSG_BUFFER_NOT_AVAIL 0x04 //!< No buffer is available. +#define INVALID_MSG_POINTER 0x05 //!< No message pointer. +#define INVALID_EVENT_ID 0x06 //!< Invalid event id. +#define INVALID_TIMEOUT 0x07 //!< Invalid timeout. +#define NO_TIMER_AVAIL 0x08 //!< No event is available. +#define NV_OPER_FAILED 0x0A //!< read a data item to NV failed. +#define INVALID_MEM_SIZE 0x0B //!< The tokens take up too much space and don't fit into Advertisement data and Scan Response Data + +/** BLE_STATUS_VALUES BLE Default BLE Status Values + * returned as bStatus_t + */ +#define bleInvalidTaskID INVALID_TASK //!< Task ID isn't setup properly +#define bleEecKeyRequestRejected 0x06 //!< key missing +#define bleNotReady 0x10 //!< Not ready to perform task +#define bleAlreadyInRequestedMode 0x11 //!< Already performing that task +#define bleIncorrectMode 0x12 //!< Not setup properly to perform that task +#define bleMemAllocError 0x13 //!< Memory allocation error occurred +#define bleNotConnected 0x14 //!< Can't perform function when not in a connection +#define bleNoResources 0x15 //!< There are no resource available +#define blePending 0x16 //!< Waiting +#define bleTimeout 0x17 //!< Timed out performing function +#define bleInvalidRange 0x18 //!< A parameter is out of range +#define bleLinkEncrypted 0x19 //!< The link is already encrypted +#define bleProcedureComplete 0x1A //!< The Procedure is completed +#define bleInvalidMtuSize 0x1B //!< SDU size is larger than peer MTU. + +/********************************LinkDB****************************************/ +// Special case connection handles +#define INVALID_CONNHANDLE 0xFFFF // Invalid connection handle, used for no connection handle +#define LOOPBACK_CONNHANDLE 0xFFFE // Loopback connection handle, used to loopback a message +// Link state flags +#define LINK_NOT_CONNECTED 0x00 // Link isn't connected +#define LINK_CONNECTED 0x01 // Link is connected +#define LINK_AUTHENTICATED 0x02 // Link is authenticated +#define LINK_BOUND 0x04 // Link is bonded +#define LINK_ENCRYPTED 0x10 // Link is encrypted +// Link Database Status callback changeTypes +#define LINKDB_STATUS_UPDATE_NEW 0 // New connection created +#define LINKDB_STATUS_UPDATE_REMOVED 1 // Connection was removed +#define LINKDB_STATUS_UPDATE_STATEFLAGS 2 // Connection state flag changed +/*******************************gattUUID***************************************/ +/** + * GATT Services + */ +#define GAP_SERVICE_UUID 0x1800 // Generic Access Profile +#define GATT_SERVICE_UUID 0x1801 // Generic Attribute Profile + +/** + * GATT Declarations + */ +#define GATT_PRIMARY_SERVICE_UUID 0x2800 // Primary Service +#define GATT_SECONDARY_SERVICE_UUID 0x2801 // Secondary Service +#define GATT_INCLUDE_UUID 0x2802 // Include +#define GATT_CHARACTER_UUID 0x2803 // Characteristic + +/** + * GATT Descriptors + */ +#define GATT_CHAR_EXT_PROPS_UUID 0x2900 // Characteristic Extended Properties +#define GATT_CHAR_USER_DESC_UUID 0x2901 // Characteristic User Description +#define GATT_CLIENT_CHAR_CFG_UUID 0x2902 // Client Characteristic Configuration +#define GATT_SERV_CHAR_CFG_UUID 0x2903 // Server Characteristic Configuration +#define GATT_CHAR_FORMAT_UUID 0x2904 // Characteristic Presentation Format +#define GATT_CHAR_AGG_FORMAT_UUID 0x2905 // Characteristic Aggregate Format +#define GATT_VALID_RANGE_UUID 0x2906 // Valid Range +#define GATT_EXT_REPORT_REF_UUID 0x2907 // External Report Reference Descriptor +#define GATT_REPORT_REF_UUID 0x2908 // Report Reference Descriptor + +/** + * GATT Characteristics + */ +#define DEVICE_NAME_UUID 0x2A00 // Device Name +#define APPEARANCE_UUID 0x2A01 // Appearance +#define PERI_PRIVACY_FLAG_UUID 0x2A02 // Peripheral Privacy Flag +#define RECONNECT_ADDR_UUID 0x2A03 // Reconnection Address +#define PERI_CONN_PARAM_UUID 0x2A04 // Peripheral Preferred Connection Parameters +#define SERVICE_CHANGED_UUID 0x2A05 // Service Changed +#define CENTRAL_ADDRESS_RESOLUTION_UUID 0x2AA6 // Central Address Resolution + +/** + * GATT Service UUIDs + */ +#define IMMEDIATE_ALERT_SERV_UUID 0x1802 // Immediate Alert +#define LINK_LOSS_SERV_UUID 0x1803 // Link Loss +#define TX_PWR_LEVEL_SERV_UUID 0x1804 // Tx Power +#define CURRENT_TIME_SERV_UUID 0x1805 // Current Time Service +#define REF_TIME_UPDATE_SERV_UUID 0x1806 // Reference Time Update Service +#define NEXT_DST_CHANGE_SERV_UUID 0x1807 // Next DST Change Service +#define GLUCOSE_SERV_UUID 0x1808 // Glucose +#define THERMOMETER_SERV_UUID 0x1809 // Health Thermometer +#define DEVINFO_SERV_UUID 0x180A // Device Information +#define NWA_SERV_UUID 0x180B // Network Availability +#define HEARTRATE_SERV_UUID 0x180D // Heart Rate +#define PHONE_ALERT_STS_SERV_UUID 0x180E // Phone Alert Status Service +#define BATT_SERV_UUID 0x180F // Battery Service +#define BLOODPRESSURE_SERV_UUID 0x1810 // Blood Pressure +#define ALERT_NOTIF_SERV_UUID 0x1811 // Alert Notification Service +#define HID_SERV_UUID 0x1812 // Human Interface Device +#define SCAN_PARAM_SERV_UUID 0x1813 // Scan Parameters +#define RSC_SERV_UUID 0x1814 // Running Speed and Cadence +#define CSC_SERV_UUID 0x1816 // Cycling Speed and Cadence +#define CYCPWR_SERV_UUID 0x1818 // Cycling Power +#define LOC_NAV_SERV_UUID 0x1819 // Location and Navigation + +/** + * GATT Characteristic UUIDs + */ +#define ALERT_LEVEL_UUID 0x2A06 // Alert Level +#define TX_PWR_LEVEL_UUID 0x2A07 // Tx Power Level +#define DATE_TIME_UUID 0x2A08 // Date Time +#define DAY_OF_WEEK_UUID 0x2A09 // Day of Week +#define DAY_DATE_TIME_UUID 0x2A0A // Day Date Time +#define EXACT_TIME_256_UUID 0x2A0C // Exact Time 256 +#define DST_OFFSET_UUID 0x2A0D // DST Offset +#define TIME_ZONE_UUID 0x2A0E // Time Zone +#define LOCAL_TIME_INFO_UUID 0x2A0F // Local Time Information +#define TIME_WITH_DST_UUID 0x2A11 // Time with DST +#define TIME_ACCURACY_UUID 0x2A12 // Time Accuracy +#define TIME_SOURCE_UUID 0x2A13 // Time Source +#define REF_TIME_INFO_UUID 0x2A14 // Reference Time Information +#define TIME_UPDATE_CTRL_PT_UUID 0x2A16 // Time Update Control Point +#define TIME_UPDATE_STATE_UUID 0x2A17 // Time Update State +#define GLUCOSE_MEAS_UUID 0x2A18 // Glucose Measurement +#define BATT_LEVEL_UUID 0x2A19 // Battery Level +#define TEMP_MEAS_UUID 0x2A1C // Temperature Measurement +#define TEMP_TYPE_UUID 0x2A1D // Temperature Type +#define IMEDIATE_TEMP_UUID 0x2A1E // Intermediate Temperature +#define MEAS_INTERVAL_UUID 0x2A21 // Measurement Interval +#define BOOT_KEY_INPUT_UUID 0x2A22 // Boot Keyboard Input Report +#define SYSTEM_ID_UUID 0x2A23 // System ID +#define MODEL_NUMBER_UUID 0x2A24 // Model Number String +#define SERIAL_NUMBER_UUID 0x2A25 // Serial Number String +#define FIRMWARE_REV_UUID 0x2A26 // Firmware Revision String +#define HARDWARE_REV_UUID 0x2A27 // Hardware Revision String +#define SOFTWARE_REV_UUID 0x2A28 // Software Revision String +#define MANUFACTURER_NAME_UUID 0x2A29 // Manufacturer Name String +#define IEEE_11073_CERT_DATA_UUID 0x2A2A // IEEE 11073-20601 Regulatory Certification Data List +#define CURRENT_TIME_UUID 0x2A2B // Current Time +#define SCAN_REFRESH_UUID 0x2A31 // Scan Refresh +#define BOOT_KEY_OUTPUT_UUID 0x2A32 // Boot Keyboard Output Report +#define BOOT_MOUSE_INPUT_UUID 0x2A33 // Boot Mouse Input Report +#define GLUCOSE_CONTEXT_UUID 0x2A34 // Glucose Measurement Context +#define BLOODPRESSURE_MEAS_UUID 0x2A35 // Blood Pressure Measurement +#define IMEDIATE_CUFF_PRESSURE_UUID 0x2A36 // Intermediate Cuff Pressure +#define HEARTRATE_MEAS_UUID 0x2A37 // Heart Rate Measurement +#define BODY_SENSOR_LOC_UUID 0x2A38 // Body Sensor Location +#define HEARTRATE_CTRL_PT_UUID 0x2A39 // Heart Rate Control Point +#define NETWORK_AVAIL_UUID 0x2A3E // Network Availability +#define ALERT_STATUS_UUID 0x2A3F // Alert Status +#define RINGER_CTRL_PT_UUID 0x2A40 // Ringer Control Point +#define RINGER_SETTING_UUID 0x2A41 // Ringer Setting +#define ALERT_CAT_ID_BMASK_UUID 0x2A42 // Alert Category ID Bit Mask +#define ALERT_CAT_ID_UUID 0x2A43 // Alert Category ID +#define ALERT_NOTIF_CTRL_PT_UUID 0x2A44 // Alert Notification Control Point +#define UNREAD_ALERT_STATUS_UUID 0x2A45 // Unread Alert Status +#define NEW_ALERT_UUID 0x2A46 // New Alert +#define SUP_NEW_ALERT_CAT_UUID 0x2A47 // Supported New Alert Category +#define SUP_UNREAD_ALERT_CAT_UUID 0x2A48 // Supported Unread Alert Category +#define BLOODPRESSURE_FEATURE_UUID 0x2A49 // Blood Pressure Feature +#define HID_INFORMATION_UUID 0x2A4A // HID Information +#define REPORT_MAP_UUID 0x2A4B // Report Map +#define HID_CTRL_PT_UUID 0x2A4C // HID Control Point +#define REPORT_UUID 0x2A4D // Report +#define PROTOCOL_MODE_UUID 0x2A4E // Protocol Mode +#define SCAN_INTERVAL_WINDOW_UUID 0x2A4F // Scan Interval Window +#define PNP_ID_UUID 0x2A50 // PnP ID +#define GLUCOSE_FEATURE_UUID 0x2A51 // Glucose Feature +#define RECORD_CTRL_PT_UUID 0x2A52 // Record Access Control Point +#define RSC_MEAS_UUID 0x2A53 // RSC Measurement +#define RSC_FEATURE_UUID 0x2A54 // RSC Feature +#define SC_CTRL_PT_UUID 0x2A55 // SC Control Point +#define CSC_MEAS_UUID 0x2A5B // CSC Measurement +#define CSC_FEATURE_UUID 0x2A5C // CSC Feature +#define SENSOR_LOC_UUID 0x2A5D // Sensor Location +#define CYCPWR_MEAS_UUID 0x2A63 // Cycling Power Measurement +#define CYCPWR_VECTOR_UUID 0x2A64 // Cycling Power Vector +#define CYCPWR_FEATURE_UUID 0x2A65 // Cycling Power Feature +#define CYCPWR_CTRL_PT_UUID 0x2A66 // Cycling Power Control Point +#define LOC_SPEED_UUID 0x2A67 // Location and Speed +#define NAV_UUID 0x2A68 // Navigation +#define POS_QUALITY_UUID 0x2A69 // Position Quality +#define LN_FEATURE_UUID 0x2A6A // LN Feature +#define LN_CTRL_PT_UUID 0x2A6B // LN Control Point +#define ELE_UUID 0x2A6C // Elevation +#define PRESSURE_UUID 0x2A6D // Pressure +#define TEMP_UUID 0x2A6E // Temperature +#define HUMI_UUID 0x2A6F // Humidity +#define TRUE_WIND_SPEED_UUID 0x2A70 // True Wind Speed +#define TRUE_WIND_DIRECTION_UUID 0x2A71 // True Wind Direction +#define URI_UUID 0x2AB6 // URI +#define MEDIA_STATE_UUID 0x2BA3 // Media State +#define MEDIA_CTRL_PT_UUID 0x2BA4 // Media Control Point +#define MEDIA_CTRL_PT_OS_UUID 0x2BA5 // Media Control Point Opcodes Supported +#define CALL_STATE_UUID 0x2BBD // Call State +#define CALL_CTRL_PT_UUID 0x2BBE // Call Control Point +#define CALL_CTRL_PT_OO_UUID 0x2BBF // Call Control Point Optional Opcodes +#define TERM_REASON_UUID 0x2BC0 // Termination Reason +#define INCOMING_CALL_UUID 0x2BC1 // Incoming Call +#define MUTE_UUID 0x2BC3 // Mute + +/** + * GATT Unit UUIDs + */ +#define GATT_UNITLESS_UUID 0x2700 // unitless +#define GATT_UNIT_LENGTH_METER_UUID 0x2701 // m, m +#define GATT_UNIT_MASS_KGRAM_UUID 0x2702 // kg, kg +#define GATT_UNIT_TIME_SECOND_UUID 0x2703 // s, s +#define GATT_UNIT_ELECTRIC_CURRENT_A_UUID 0x2704 // A, A +#define GATT_UNIT_THERMODYN_TEMP_K_UUID 0x2705 // K, K +#define GATT_UNIT_AMOUNT_SUBSTANCE_M_UUID 0x2706 // mol, mol +#define GATT_UNIT_LUMINOUS_INTENSITY_C_UUID 0x2707 // cd, cd + +#define GATT_UNIT_AREA_SQ_MTR_UUID 0x2710 // m^2, m^2 +#define GATT_UNIT_VOLUME_CUBIC_MTR_UUID 0x2711 // m^3, m^3 +#define GATT_UNIT_VELOCITY_MPS_UUID 0x2712 // m/s, m s^-1 +#define GATT_UNIT_ACCELERATION_MPS_SQ_UUID 0x2713 // m/s^2, m s^-2 +#define GATT_UNIT_WAVENUMBER_RM_UUID 0x2714 // ? m^-1 +#define GATT_UNIT_DENSITY_KGPCM_UUID 0x2715 // p, kg m^-3 +#define GATT_UNIT_SURFACE_DENSITY_KGPSM_UUID 0x2716 // pA, kg m^-2 +#define GATT_UNIT_SPECIFIC_VOLUME_CMPKG_UUID 0x2717 // v, m^3 kg^-1 +#define GATT_UNIT_CURRENT_DENSITY_APSM_UUID 0x2718 // j, A m^-2 +#define GATT_UNIT_MAG_FIELD_STRENGTH_UUID 0x2719 // H, A m +#define GATT_UNIT_AMOUNT_CONC_MPCM_UUID 0x271A // c, mol m^-3 +#define GATT_UNIT_MASS_CONC_KGPCM_UUID 0x271B // c, kg m^-3 +#define GATT_UNIT_LUMINANCE_CPSM_UUID 0x271C // Lv, cd m^-2 +#define GATT_UNIT_REFRACTIVE_INDEX_UUID 0x271D // n, 1 +#define GATT_UNIT_RELATIVE_PERMEABLILTY_UUID 0x271E // u, 1 +#define GATT_UNIT_PLANE_ANGLE_RAD_UUID 0x2720 // rad, m m-1 +#define GATT_UNIT_SOLID_ANGLE_STERAD_UUID 0x2721 // sr, m2 m-2 +#define GATT_UNIT_FREQUENCY_HTZ_UUID 0x2722 // Hz, s-1 +#define GATT_UNIT_FORCE_NEWTON_UUID 0x2723 // N, m kg s-2 +#define GATT_UNIT_PRESSURE_PASCAL_UUID 0x2724 // Pa, N/m2 = m2 kg s-2 +#define GATT_UNIT_ENERGY_JOULE_UUID 0x2725 // J, N m = m2 kg s-2 +#define GATT_UNIT_POWER_WATT_UUID 0x2726 // W, J/s = m2 kg s-3 +#define GATT_UNIT_E_CHARGE_C_UUID 0x2727 // C, sA +#define GATT_UNIT_E_POTENTIAL_DIF_V_UUID 0x2728 // V, W/A = m2 kg s-3 A-1 + +#define GATT_UNIT_CELSIUS_TEMP_DC_UUID 0x272F // oC, t/oC = T/K - 273.15 + +#define GATT_UNIT_TIME_MINUTE_UUID 0x2760 // min, 60 s +#define GATT_UNIT_TIME_HOUR_UUID 0x2761 // h, 3600 s +#define GATT_UNIT_TIME_DAY_UUID 0x2762 // d, 86400 s +#define GATT_UNIT_PLANE_ANGLE_DEGREE_UUID 0x2763 // o, (pi/180) rad +#define GATT_UNIT_PLANE_ANGLE_MINUTE_UUID 0x2764 // ', (pi/10800) rad +#define GATT_UNIT_PLANE_ANGLE_SECOND_UUID 0x2765 // '', (pi/648000) rad +#define GATT_UNIT_AREA_HECTARE_UUID 0x2766 // ha, 10^4 m^2 +#define GATT_UNIT_VOLUME_LITRE_UUID 0x2767 // l, 10^-3 m^3 +#define GATT_UNIT_MASS_TONNE_UUID 0x2768 // t, 10^3 kg + +#define GATT_UINT_LENGTH_YARD_UUID 0x27A0 // yd, 0.9144 m +#define GATT_UNIT_LENGTH_PARSEC_UUID 0x27A1 // pc, 3.085678 ?1016 m +#define GATT_UNIT_LENGTH_INCH_UUID 0x27A2 // in, 0.0254 m +#define GATT_UNIT_LENGTH_FOOT_UUID 0x27A3 // ft, 0.3048 m +#define GATT_UNIT_LENGTH_MILE_UUID 0x27A4 // mi, 1609.347 m +#define GATT_UNIT_PRESSURE_PFPSI_UUID 0x27A5 // psi, 6.894757 ?103 Pa +#define GATT_UNIT_VELOCITY_KMPH_UUID 0x27A6 // km/h, 0.2777778 m^s-1 +#define GATT_UNIT_VELOCITY_MPH_UUID 0x27A7 // mi/h, 0.44704 m^ s-1 +#define GATT_UNIT_ANGULAR_VELOCITY_RPM_UUID 0x27A8 // r/min, 0.1047198 rad s-1 +#define GATT_UNIT_ENERGY_GCAL_UUID 0x27A9 // energy (gram calorie) +#define GATT_UNIT_ENERGY_KCAL_UUID 0x27AA // kcal, 4190.02 J +#define GATT_UNIT_ENERGY_KWH_UUID 0x27AB // kWh, 3600000 J +#define GATT_UNIT_THERMODYN_TEMP_DF_UUID 0x27AC // oF, t/oF = T/K ?1.8 - 459.67 +#define GATT_UNIT_PERCENTAGE_UUID 0x27AD // percentage,% +#define GATT_UNIT_PER_MILE_UUID 0x27AE // per mille +#define GATT_UNIT_PERIOD_BPM_UUID 0x27AF // period (beats per minute),BPM +#define GATT_UNIT_E_CHARGE_AH_UUID 0x27B0 // electric charge (ampere hours) +#define GATT_UNIT_MASS_DENSITY_MGPD_UUID 0x27B1 // mass density (milligram per decilitre) +#define GATT_UNIT_MASS_DENSITY_MMPL_UUID 0x27B2 // mass density (millimole per litre) +#define GATT_UNIT_TIME_YEAR_UUID 0x27B3 // time (year) +#define GATT_UNIT_TIME_MONTH_UUID 0x27B4 // time (month) + +/*********************************Messages IDs*********************************/ +// GATT - Messages IDs +#define GATT_MSG_EVENT 0xB0 //!< Incoming GATT message +#define GATT_SERV_MSG_EVENT 0xB1 //!< Incoming GATT ServApp message +// GAP - Messages IDs +#define GAP_MSG_EVENT 0xD0 //!< Incoming GAP message +/************************************ATT***************************************/ +#define ATT_MTU_SIZE 23 //!< Minimum ATT MTU size +#define ATT_MAX_MTU_SIZE 512 //!< Maximum ATT MTU size +// ATT Methods +#define ATT_ERROR_RSP 0x01 //!< ATT Error Response +#define ATT_EXCHANGE_MTU_REQ 0x02 //!< ATT Exchange MTU Request +#define ATT_EXCHANGE_MTU_RSP 0x03 //!< ATT Exchange MTU Response +#define ATT_FIND_INFO_REQ 0x04 //!< ATT Find Information Request +#define ATT_FIND_INFO_RSP 0x05 //!< ATT Find Information Response +#define ATT_FIND_BY_TYPE_VALUE_REQ 0x06 //!< ATT Find By Type Value Request +#define ATT_FIND_BY_TYPE_VALUE_RSP 0x07 //!< ATT Find By Type Value Response +#define ATT_READ_BY_TYPE_REQ 0x08 //!< ATT Read By Type Request +#define ATT_READ_BY_TYPE_RSP 0x09 //!< ATT Read By Type Response +#define ATT_READ_REQ 0x0a //!< ATT Read Request +#define ATT_READ_RSP 0x0b //!< ATT Read Response +#define ATT_READ_BLOB_REQ 0x0c //!< ATT Read Blob Request +#define ATT_READ_BLOB_RSP 0x0d //!< ATT Read Blob Response +#define ATT_READ_MULTI_REQ 0x0e //!< ATT Read Multiple Request +#define ATT_READ_MULTI_RSP 0x0f //!< ATT Read Multiple Response +#define ATT_READ_BY_GRP_TYPE_REQ 0x10 //!< ATT Read By Group Type Request +#define ATT_READ_BY_GRP_TYPE_RSP 0x11 //!< ATT Read By Group Type Response +#define ATT_WRITE_REQ 0x12 //!< ATT Write Request +#define ATT_WRITE_RSP 0x13 //!< ATT Write Response +#define ATT_PREPARE_WRITE_REQ 0x16 //!< ATT Prepare Write Request +#define ATT_PREPARE_WRITE_RSP 0x17 //!< ATT Prepare Write Response +#define ATT_EXECUTE_WRITE_REQ 0x18 //!< ATT Execute Write Request +#define ATT_EXECUTE_WRITE_RSP 0x19 //!< ATT Execute Write Response +#define ATT_HANDLE_VALUE_NOTI 0x1b //!< ATT Handle Value Notification +#define ATT_HANDLE_VALUE_IND 0x1d //!< ATT Handle Value Indication +#define ATT_HANDLE_VALUE_CFM 0x1e //!< ATT Handle Value Confirmation + +#define ATT_WRITE_CMD 0x52 //!< ATT Write Command +#define ATT_SIGNED_WRITE_CMD 0xD2 //!< ATT Signed Write Command + +// ATT Error Codes +#define ATT_ERR_INVALID_HANDLE 0x01 //!< The attribute handle given was not valid on this server +#define ATT_ERR_READ_NOT_PERMITTED 0x02 //!< The attribute cannot be read +#define ATT_ERR_WRITE_NOT_PERMITTED 0x03 //!< The attribute cannot be written +#define ATT_ERR_INVALID_PDU 0x04 //!< The attribute PDU was invalid +#define ATT_ERR_INSUFFICIENT_AUTHEN 0x05 //!< The attribute requires authentication before it can be read or written +#define ATT_ERR_UNSUPPORTED_REQ 0x06 //!< Attribute server does not support the request received from the client +#define ATT_ERR_INVALID_OFFSET 0x07 //!< Offset specified was past the end of the attribute +#define ATT_ERR_INSUFFICIENT_AUTHOR 0x08 //!< The attribute requires authorization before it can be read or written +#define ATT_ERR_PREPARE_QUEUE_FULL 0x09 //!< Too many prepare writes have been queued +#define ATT_ERR_ATTR_NOT_FOUND 0x0a //!< No attribute found within the given attribute handle range +#define ATT_ERR_ATTR_NOT_LONG 0x0b //!< The attribute cannot be read using the Read Blob Request +#define ATT_ERR_INSUFFICIENT_KEY_SIZE 0x0c //!< The Encryption Key Size used for encrypting this link is insufficient +#define ATT_ERR_INVALID_VALUE_SIZE 0x0d //!< The attribute value length is invalid for the operation +#define ATT_ERR_UNLIKELY 0x0e //!< The attribute request that was requested has encountered an error that was very unlikely, and therefore could not be completed as requested +#define ATT_ERR_INSUFFICIENT_ENCRYPT 0x0f //!< The attribute requires encryption before it can be read or written +#define ATT_ERR_UNSUPPORTED_GRP_TYPE 0x10 //!< The attribute type is not a supported grouping attribute as defined by a higher layer specification +#define ATT_ERR_INSUFFICIENT_RESOURCES 0x11 //!< Insufficient Resources to complete the request +#define ATT_ERR_INVALID_VALUE 0x80 //!< The attribute value is invalid for the operation + +/********************************************************************* + * ATT Find By Type Value Response macros + */ +// Attribute Handle and Group End Handle pair indexes +#define ATT_ATTR_HANDLE_IDX( i ) ( (i) * (2 + 2) ) +#define ATT_GRP_END_HANDLE_IDX( i ) ( ATT_ATTR_HANDLE_IDX( (i) ) + 2 ) + +#define ATT_ATTR_HANDLE( info, i ) ( BUILD_UINT16( (info)[ATT_ATTR_HANDLE_IDX((i))], \ + (info)[ATT_ATTR_HANDLE_IDX((i))+1] ) ) +#define ATT_GRP_END_HANDLE( info, i ) ( BUILD_UINT16( (info)[ATT_GRP_END_HANDLE_IDX((i))], \ + (info)[ATT_GRP_END_HANDLE_IDX((i))+1] ) ) +/** @defgroup ATT_MSG_EVENT_DEFINES ATT Message Event IDs + * @{ + */ +#define ATT_FLOW_CTRL_VIOLATED_EVENT 0x7E //!< Sent when ATT flow control is violated on a connection. This event is sent as an TMOS message defined as attFlowCtrlViolatedEvt_t. +#define ATT_MTU_UPDATED_EVENT 0x7F //!< Sent when MTU is updated for a connection. This event is sent as an TMOS message defined as attMtuUpdatedEvt_t. +/** @} End ATT_MSG_EVENT_DEFINES */ + +/*** Opcode fields: bitmasks ***/ +// Size of 16-bit Bluetooth UUID +#define ATT_BT_UUID_SIZE 2 +// Size of 128-bit UUID +#define ATT_UUID_SIZE 16 +/******************************** GATT ***********************************/ + +// GATT Attribute Access Permissions Bit Fields +#define GATT_PERMIT_READ 0x01 //!< Attribute is Readable +#define GATT_PERMIT_WRITE 0x02 //!< Attribute is Writable +#define GATT_PERMIT_AUTHEN_READ 0x04 //!< Read requires Authentication +#define GATT_PERMIT_AUTHEN_WRITE 0x08 //!< Write requires Authentication +#define GATT_PERMIT_AUTHOR_READ 0x10 //!< Read requires Authorization +#define GATT_PERMIT_AUTHOR_WRITE 0x20 //!< Write requires Authorization +#define GATT_PERMIT_ENCRYPT_READ 0x40 //!< Read requires Encryption +#define GATT_PERMIT_ENCRYPT_WRITE 0x80 //!< Write requires Encryption + +// GATT Characteristic Properties Bit Fields +#define GATT_PROP_BCAST 0x01 //!< Permits broadcasts of the Characteristic Value +#define GATT_PROP_READ 0x02 //!< Permits reads of the Characteristic Value +#define GATT_PROP_WRITE_NO_RSP 0x04 //!< Permits writes of the Characteristic Value without response +#define GATT_PROP_WRITE 0x08 //!< Permits writes of the Characteristic Value with response +#define GATT_PROP_NOTIFY 0x10 //!< Permits notifications of a Characteristic Value without acknowledgement +#define GATT_PROP_INDICATE 0x20 //!< Permits indications of a Characteristic Value with acknowledgement +#define GATT_PROP_AUTHEN 0x40 //!< Permits signed writes to the Characteristic Value +#define GATT_PROP_EXTENDED 0x80 //!< Additional characteristic properties are defined in the Characteristic Extended Properties Descriptor + +// GATT local read or write operation +#define GATT_LOCAL_READ 0xFF +#define GATT_LOCAL_WRITE 0xFE + +// GATT Encryption Key Size Limits +#define GATT_MIN_ENCRYPT_KEY_SIZE 7 //!< GATT Minimum Encryption Key Size +#define GATT_MAX_ENCRYPT_KEY_SIZE 16 //!< GATT Maximum Encryption Key Size + +// Attribute handle definitions +#define GATT_INVALID_HANDLE 0x0000 // Invalid attribute handle +#define GATT_MIN_HANDLE 0x0001 // Minimum attribute handle +#define GATT_MAX_HANDLE 0xFFFF // Maximum attribute handle + +#define GATT_MAX_MTU 0xFFFF // Maximum MTU size + +// Attribute Access Permissions +#define gattPermitRead( a ) ( (a) & GATT_PERMIT_READ ) +#define gattPermitWrite( a ) ( (a) & GATT_PERMIT_WRITE ) +#define gattPermitAuthenRead( a ) ( (a) & GATT_PERMIT_AUTHEN_READ ) +#define gattPermitAuthenWrite( a ) ( (a) & GATT_PERMIT_AUTHEN_WRITE ) +#define gattPermitAuthorRead( a ) ( (a) & GATT_PERMIT_AUTHOR_READ ) +#define gattPermitAuthorWrite( a ) ( (a) & GATT_PERMIT_AUTHOR_WRITE ) +#define gattPermitEncryptRead( a ) ( (a) & GATT_PERMIT_ENCRYPT_READ ) +#define gattPermitEncryptWrite( a ) ( (a) & GATT_PERMIT_ENCRYPT_WRITE ) + +// Check for different UUID types +#define gattPrimaryServiceType( t ) ( ATT_CompareUUID( primaryServiceUUID, ATT_BT_UUID_SIZE, (t).uuid, (t).len ) ) +#define gattSecondaryServiceType( t ) ( ATT_CompareUUID( secondaryServiceUUID, ATT_BT_UUID_SIZE, (t).uuid, (t).len ) ) +#define gattCharacterType( t ) ( ATT_CompareUUID( characterUUID, ATT_BT_UUID_SIZE, (t).uuid, (t).len ) ) +#define gattIncludeType( t ) ( ATT_CompareUUID( includeUUID, ATT_BT_UUID_SIZE, (t).uuid, (t).len ) ) +#define gattServiceType( t ) ( gattPrimaryServiceType( (t) ) || gattSecondaryServiceType( (t) ) ) +#define GATT_MAX_NUM_CONN (4) + +// GATT Client Characteristic Configuration Bit Fields +#define GATT_CLIENT_CFG_NOTIFY 0x0001 //!< The Characteristic Value shall be notified +#define GATT_CLIENT_CFG_INDICATE 0x0002 //!< The Characteristic Value shall be indicated + +#define GATT_CFG_NO_OPERATION 0x0000 // No operation + +// All profile services bit fields +#define GATT_ALL_SERVICES 0xFFFFFFFF + +// The number of attribute records in a given attribute table +#define GATT_NUM_ATTRS( attrs ) ( sizeof( attrs ) / sizeof( gattAttribute_t ) ) + +// The handle of a service is the handle of the first attribute +#define GATT_SERVICE_HANDLE( attrs ) ( (attrs)[0].handle ) + +// The handle of the first included service (i = 1) is the value of the second attribute +#define GATT_INCLUDED_HANDLE( attrs, i ) ( *((uint16_t *)((attrs)[(i)].pValue)) ) + +// Client Characteristic Configuration table (from CCC attribute value pointer) +#define GATT_CCC_TBL( pValue ) ( (gattCharCfg_t *)(*((PTR_TYPE)(&pValue)))) + +/************************************ GAP *************************************/ +#define GAP_MSG_EVENT_DEFINES //!< GAP type of command +#define GAP_DEVICE_INIT_DONE_EVENT 0x00 //!< Sent when the Device Initialization is complete. This event is sent as an tmos message defined as gapDeviceInitDoneEvent_t. +#define GAP_DEVICE_DISCOVERY_EVENT 0x01 //!< Sent when the Device Discovery Process is complete. This event is sent as an tmos message defined as gapDevDiscEvent_t. +#define GAP_ADV_DATA_UPDATE_DONE_EVENT 0x02 //!< Sent when the Advertising Data or SCAN_RSP Data has been updated. This event is sent as an tmos message defined as gapAdvDataUpdateEvent_t. +#define GAP_MAKE_DISCOVERABLE_DONE_EVENT 0x03 //!< Sent when the Make Discoverable Request is complete. This event is sent as an tmos message defined as gapMakeDiscoverableRspEvent_t. +#define GAP_END_DISCOVERABLE_DONE_EVENT 0x04 //!< Sent when the Advertising has ended. This event is sent as an tmos message defined as gapEndDiscoverableRspEvent_t. +#define GAP_LINK_ESTABLISHED_EVENT 0x05 //!< Sent when the Establish Link Request is complete. This event is sent as an tmos message defined as gapEstLinkReqEvent_t. +#define GAP_LINK_TERMINATED_EVENT 0x06 //!< Sent when a connection was terminated. This event is sent as an tmos message defined as gapTerminateLinkEvent_t. +#define GAP_LINK_PARAM_UPDATE_EVENT 0x07 //!< Sent when an Update Parameters Event is received. This event is sent as an tmos message defined as gapLinkUpdateEvent_t. +#define GAP_RANDOM_ADDR_CHANGED_EVENT 0x08 //!< Sent when a random address was changed. This event is sent as an tmos message defined as gapRandomAddrEvent_t. +#define GAP_SIGNATURE_UPDATED_EVENT 0x09 //!< Sent when the device's signature counter is updated. This event is sent as an tmos message defined as gapSignUpdateEvent_t. +#define GAP_AUTHENTICATION_COMPLETE_EVENT 0x0A //!< Sent when the Authentication (pairing) process is complete. This event is sent as an tmos message defined as gapAuthCompleteEvent_t. +#define GAP_PASSKEY_NEEDED_EVENT 0x0B //!< Sent when a Passkey is needed. This is part of the pairing process. This event is sent as an tmos message defined as gapPasskeyNeededEvent_t. +#define GAP_SLAVE_REQUESTED_SECURITY_EVENT 0x0C //!< Sent when a Slave Security Request is received. This event is sent as an tmos message defined as gapSlaveSecurityReqEvent_t. +#define GAP_DEVICE_INFO_EVENT 0x0D //!< Sent during the Device Discovery Process when a device is discovered. This event is sent as an tmos message defined as gapDeviceInfoEvent_t. +#define GAP_BOND_COMPLETE_EVENT 0x0E //!< Sent when the bonding process is complete. This event is sent as an tmos message defined as gapBondCompleteEvent_t. +#define GAP_PAIRING_REQ_EVENT 0x0F //!< Sent when an unexpected Pairing Request is received. This event is sent as an tmos message defined as gapPairingReqEvent_t. +#define GAP_DIRECT_DEVICE_INFO_EVENT 0x10 //!< Sent when a direct Advertising Data is received. This event is sent as an tmos message defined as gapDirectDeviceInfoEvent_t. +#define GAP_PHY_UPDATE_EVENT 0x11 //!< Sent when a PHY Update Event is received. This event is sent as an tmos message defined as gapLinkUpdateEvent_t. +#define GAP_EXT_ADV_DEVICE_INFO_EVENT 0x12 //!< Sent when a Extended Advertising Data is received. This event is sent as an tmos message defined as gapExtAdvDeviceInfoEvent_t. +#define GAP_MAKE_PERIODIC_ADV_DONE_EVENT 0x13 //!< Sent when the Set Periodic Advertising enable is complete. This event is sent as an tmos message defined as gapMakePeriodicRspEvent_t. +#define GAP_END_PERIODIC_ADV_DONE_EVENT 0x14 //!< Sent when the Set Periodic Advertising disable is complete. This event is sent as an tmos message defined as gapEndPeriodicRspEvent_t. +#define GAP_SYNC_ESTABLISHED_EVENT 0x15 //!< Sent when a Periodic Advertising Sync Establish is complete. This event is sent as an tmos message defined as gapSyncEstablishedEvent_t. +#define GAP_PERIODIC_ADV_DEVICE_INFO_EVENT 0x16 //!< Sent when a Periodic Advertising Data is received. This event is sent as an tmos message defined as gapPeriodicAdvDeviceInfoEvent_t. +#define GAP_SYNC_LOST_EVENT 0x17 //!< Sent when a Periodic Advertising Sync was lost. This event is sent as an tmos message defined as gapSyncLostEvent_t. +#define GAP_SCAN_REQUEST_EVENT 0x19 //!< Sent when a SCAN_REQ PDU or an AUX_SCAN_REQ PDU has been received by the advertiser. This event is sent as an tmos message defined as gapScanReqReseiveEvent_t. +#define GAP_OOB_NEEDED_EVENT 0x1A //!< resv +#define GAP_MAKE_CONNECTIONESS_CTE_DONE_EVENT 0x1B //!< Sent when the Set Connectionless CTE Transmit enable is complete. This event is sent as an tmos message defined as gapMakeConnectionlessCTERspEvent_t. +#define GAP_END_CONNECTIONESS_CTE_DONE_EVENT 0x1C //!< Sent when the Set Connectionless CTE Transmit disable is complete. This event is sent as an tmos message defined as gapEndConnectionlessCTERspEvent_t. +#define GAP_PERI_ADV_SYNC_TRAN_RECEIVED_EVENT 0x1D //!< Sent when the periodic advertising sync transfer received. This event is sent as an tmos message defined as gapPeriTranReceivec_t. + +// GAP_PROFILE_ROLE_DEFINES GAP Profile Roles +#define GAP_PROFILE_BROADCASTER 0x01 //!< A device that sends advertising events only. +#define GAP_PROFILE_OBSERVER 0x02 //!< A device that receives advertising events only. +#define GAP_PROFILE_PERIPHERAL 0x04 //!< A device that accepts the establishment of an LE physical link using the connection establishment procedure +#define GAP_PROFILE_CENTRAL 0x08 //!< A device that supports the Central role initiates the establishment of a physical connection + +// GAP Status Return Values - returned as bStatus_t +#define bleGAPUserCanceled 0x30 //!< The user canceled the task +#define bleGAPConnNotAcceptable 0x31 //!< The connection was not accepted +#define bleGAPBondRejected 0x32 //!< The bond information was rejected. +#define bleGAPExpiredCanceled 0x33 //!< The duration has expired + +#define GAP_DEVICE_NAME_LEN 21 // Excluding null-terminate char + +// option defined +#define LISTEN_PERIODIC_ADVERTISING_MODE (1<<0) //!< used to determine whether the Periodic Advertiser List is used +#define REPORTING_INITIALLY_DISABLED (1<<1) //!< 0: Reporting initially enabled 1: Reporting initially disabled +#define DUPLICATE_FILTERING_INITIALLY_ENABLED (1<<2) //!< 0: Duplicate filtering initially disabled 1: Duplicate filtering initially enabled + +/*------------------------------------------------------------------- + * CONSTANTS + */ +/** @defgroup GAP_CONN_HANDLE_DEFINES GAP Special Connection Handles + * Used by GAP_TerminateLinkReq() + * @{ + */ +#define GAP_CONNHANDLE_INIT 0xFFFE //!< terminates a link create +#define GAP_CONNHANDLE_ALL 0xFFFF //!< terminates all links for the matching task ID. +/** @} End GAP_CONN_HANDLE_DEFINES */ + +// Privacy Flag States +#define GAP_PRIVACY_DISABLED 0x00 +#define GAP_PRIVACY_ENABLED 0x01 + +// GAP GATT Server Parameters used with GGS Get/Set Parameter and Application's Callback functions +#define GGS_DEVICE_NAME_ATT 0 // RW uint8_t[GAP_DEVICE_NAME_LEN] +#define GGS_APPEARANCE_ATT 1 // RW uint16_t +#define GGS_PERI_PRIVACY_FLAG_ATT 2 // RW uint8_t +#define GGS_RECONNCT_ADDR_ATT 3 // RW uint8_t[B_ADDR_LEN] +#define GGS_PERI_CONN_PARAM_ATT 4 // RW sizeof(gapPeriConnectParams_t) +#define GGS_PERI_PRIVACY_FLAG_PROPS 5 // RW uint8_t +#define GGS_W_PERMIT_DEVICE_NAME_ATT 6 // W uint8_t +#define GGS_W_PERMIT_APPEARANCE_ATT 7 // W uint8_t +#define GGS_W_PERMIT_PRIVACY_FLAG_ATT 8 // W uint8_t +#define GGS_CENT_ADDR_RES_ATT 9 // RW uint8_t +// GAP Services bit fields +#define GAP_SERVICE 0x00000001 + +// GAP_PARAMETER_ID_DEFINES GAP Parameter IDs +// Timers +#define TGAP_GEN_DISC_ADV_MIN 0 //!< Minimum time to remain advertising, when in Discoverable mode.Default 0-turns off the timeout. (n * 0.625 mSec). +#define TGAP_LIM_ADV_TIMEOUT 1 //!< Maximum time to remain advertising, when in Limited Discoverable mode.Default 180 seconds. (n * 1 seconds) +#define TGAP_DISC_SCAN 2 //!< Minimum time to perform scanning,Setting this parameter to 0 turns off the timeout.Default 10.24seconds. (n * 0.625 mSec) + +// when in General Discovery process +#define TGAP_DISC_ADV_INT_MIN 3 //!< Minimum advertising interval.Default 160. (n * 0.625 mSec) +#define TGAP_DISC_ADV_INT_MAX 4 //!< Maximum advertising interval.Default 160. (n * 0.625 mSec) +#define TGAP_DISC_SCAN_INT 5 //!< Scan interval used during Link Layer Scanning state.Default 16. (n * 0.625 mSec) +#define TGAP_DISC_SCAN_WIND 6 //!< Scan window used during Link Layer Scanning state.Default 16. (n * 0.625 mSec) + +// when in Connection Establishment process(1M PHY) +#define TGAP_CONN_EST_INT_MIN 7 //!< Minimum Link Layer connection interval.Default 80. (n * 1.25 mSec) +#define TGAP_CONN_EST_INT_MAX 8 //!< Maximum Link Layer connection interval.Default 80. (n * 1.25 mSec) +#define TGAP_CONN_EST_SCAN_INT 9 //!< Scan interval used during Link Layer Initiating state.Default 16. (n * 0.625 mSec) +#define TGAP_CONN_EST_SCAN_WIND 10 //!< Scan window used during Link Layer Initiating state.Default 16. (n * 0.625 mSec) +#define TGAP_CONN_EST_HIGH_SCAN_INT 11 //!< Scan interval used during Link Layer Initiating state, high duty scan cycle scan parameters (n * 0.625 mSec) +#define TGAP_CONN_EST_HIGH_SCAN_WIND 12 //!< Scan window used during Link Layer Initiating state, high duty scan cycle scan parameters (n * 0.625 mSec) +#define TGAP_CONN_EST_SUPERV_TIMEOUT 13 //!< Link Layer connection supervision timeout.Default 2000. (n * 10 mSec) +#define TGAP_CONN_EST_LATENCY 14 //!< Link Layer connection slave latency.Default 0. (in number of connection events) +#define TGAP_CONN_EST_MIN_CE_LEN 15 //!< Local informational parameter about minimum length of connection needed.Default 0. (n * 0.625 mSec) +#define TGAP_CONN_EST_MAX_CE_LEN 16 //!< Local informational parameter about maximum length of connection needed.Default 0. (n * 0.625 mSec) + +// Proprietary +#define TGAP_PRIVATE_ADDR_INT 17 //!< Minimum Time Interval between private (resolvable) address changes.Default 900. (n * 1 seconds) +#define TGAP_SM_TIMEOUT 18 //!< SM Message Timeout (milliseconds). Default 30 seconds. +#define TGAP_SM_MIN_KEY_LEN 19 //!< SM Minimum Key Length supported. Default 7. +#define TGAP_SM_MAX_KEY_LEN 20 //!< SM Maximum Key Length supported. Default 16. +#define TGAP_FILTER_ADV_REPORTS 21 //!< Filter duplicate advertising reports. Default TRUE. +#define TGAP_SCAN_RSSI_MIN 22 //!< Minimum RSSI required for scan advertising to be reported to the app. Default -127. +#define TGAP_REJECT_CONN_PARAMS 23 //!< Whether or not to reject Connection Parameter Update Request received on Central device. Default FALSE. +#define TGAP_AUTH_TASK_ID 24 //!< Task ID override for Task Authentication control (for stack internal use only) + +// v5.x +#define TGAP_ADV_TX_POWER 25 //!< Indicates the maximum power level Range: -127 �� N �� +126 Units: dBm.Default 127(Host has no preference). +#define TGAP_ADV_PRIMARY_PHY 26 //!< Indicates the PHY on which the advertising packets are transmitted on the primary advertising channel.LE 1M/LE Coded.Default GAP_PHY_VAL_LE_1M. +#define TGAP_ADV_SECONDARY_PHY 27 //!< LE 1M/LE 2M/LE Coded. Default GAP_PHY_VAL_LE_1M. +#define TGAP_ADV_SECONDARY_MAX_SKIP 28 //!< Maximum advertising events the Controller can skip before sending the AUX_ADV_IND packets on the secondary advertising channel. Default 0. +#define TGAP_ADV_ADVERTISING_SID 29 //!< Value of the Advertising SID subfield in the ADI field of the PDU Range:0-15. Default 0. +#define TGAP_ADV_SCAN_REQ_NOTIFY 30 //!< Scan request notifications enabled.Default 0-disabled. +#define TGAP_ADV_ADVERTISING_DURATION 31 //!< Advertising duration Range: 0x0001 - 0xFFFF Time = N * 10ms. Default 0-No advertising duration. +#define TGAP_ADV_MAX_EVENTS 32 //!< indicates the maximum number of extended advertising events.Range: 0x00 - 0xFF. Default 0(No maximum number of advertising events). + +// when in General Discovery process +#define TGAP_DISC_SCAN_PHY 33 //!< LE 1M/LE Coded. Default GAP_PHY_BIT_LE_1M. +#define TGAP_DISC_SCAN_CODED_INT 34 //!< Scan interval used during Link Layer coded Scanning state, when in General Discovery process (n * 0.625 mSec) +#define TGAP_DISC_SCAN_CODED_WIND 35 //!< Scan window used during Link Layer coded Scanning state, when in General Discovery process (n * 0.625 mSec) +#define TGAP_DISC_SCAN_DURATION 36 //!< Scan duration Range: 0x0001 - 0xFFFF Time = N * 10 ms. Default 0-Scan continuously until explicitly disable. +#define TGAP_DISC_SCAN_PERIOD 37 //!< resv. + +// when in Connection Establishment process(2M PHY) +#define TGAP_CONN_EST_INT_PHY 38 //!< LE 1M/LE Coded. Default GAP_PHY_BIT_LE_1M. +#define TGAP_CONN_EST_2M_INT_MIN 39 //!< Minimum Link Layer connection interval.Default 80. (n * 1.25 mSec) +#define TGAP_CONN_EST_2M_INT_MAX 40 //!< Maximum Link Layer connection interval.Default 80. (n * 1.25 mSec) +#define TGAP_CONN_EST_2M_SUPERV_TIMEOUT 41 //!< Link Layer connection supervision timeout.Default 2000. (n * 10 mSec) +#define TGAP_CONN_EST_2M_LATENCY 42 //!< Link Layer connection slave latency.Default 0. (in number of connection events) +#define TGAP_CONN_EST_2M_MIN_CE_LEN 43 //!< Local informational parameter about minimum length of connection needed.Default 0. (n * 0.625 mSec) +#define TGAP_CONN_EST_2M_MAX_CE_LEN 44 //!< Local informational parameter about maximum length of connection needed.Default 0. (n * 0.625 mSec) + +// when in Connection Establishment process(Coded PHY) +#define TGAP_CONN_EST_CODED_INT_MIN 45 //!< Minimum Link Layer connection interval.Default 80. (n * 1.25 mSec) +#define TGAP_CONN_EST_CODED_INT_MAX 46 //!< Maximum Link Layer connection interval.Default 80. (n * 1.25 mSec) +#define TGAP_CONN_EST_CODED_SCAN_INT 47 //!< Scan interval used during Link Layer Initiating state.Default 16. (n * 0.625 mSec) +#define TGAP_CONN_EST_CODED_SCAN_WIND 48 //!< Scan window used during Link Layer Initiating state.Default 16. (n * 0.625 mSec) +#define TGAP_CONN_EST_CODED_HIGH_SCAN_INT 49 //!< Scan interval used during Link Layer Initiating state, high duty scan cycle scan parameters (n * 0.625 mSec) +#define TGAP_CONN_EST_CODED_HIGH_SCAN_WIND 50 //!< Scan window used during Link Layer Initiating state, high duty scan cycle scan parameters (n * 0.625 mSec) +#define TGAP_CONN_EST_CODED_SUPERV_TIMEOUT 51 //!< Link Layer connection supervision timeout.Default 2000. (n * 10 mSec) +#define TGAP_CONN_EST_CODED_LATENCY 52 //!< Link Layer connection slave latency.Default 0. (in number of connection events) +#define TGAP_CONN_EST_CODED_MIN_CE_LEN 53 //!< Local informational parameter about minimum length of connection needed.Default 0. (n * 0.625 mSec) +#define TGAP_CONN_EST_CODED_MAX_CE_LEN 54 //!< Local informational parameter about maximum length of connection needed.Default 0. (n * 0.625 mSec) + +// periodic advertising +#define TGAP_PERIODIC_ADV_INT_MIN 55 //!< Minimum periodic advertising interval.Range: 0x0006 to 0xFFFF.Default 160. (n * 1.25 mSec) +#define TGAP_PERIODIC_ADV_INT_MAX 56 //!< Maximum periodic advertising interval.Range: 0x0006 to 0xFFFF.Default 160. (n * 1.25 mSec) +#define TGAP_PERIODIC_ADV_PROPERTIES 57 //!< Include TxPower in the periodic advertising PDU. + +#define TGAP_SCAN_MAX_LENGTH 58 //!< Extended scan maximum data length.Default 460 +#define TGAP_AFH_CHANNEL_MDOE 59 //!< whether t he Controller's channel assessment scheme is enabled or disabled.Default disabled. + +#define TGAP_PARAMID_MAX 60 //!< ID MAX-valid Parameter ID + +// GAP_DEVDISC_MODE_DEFINES GAP Device Discovery Modes +#define DEVDISC_MODE_NONDISCOVERABLE 0x00 //!< No discoverable setting +#define DEVDISC_MODE_GENERAL 0x01 //!< General Discoverable devices +#define DEVDISC_MODE_LIMITED 0x02 //!< Limited Discoverable devices +#define DEVDISC_MODE_ALL 0x03 //!< Not filtered + +// GAP_ADDR_TYPE_DEFINES GAP Address Types +#define ADDRTYPE_PUBLIC 0x00 //!< Use the BD_ADDR +#define ADDRTYPE_STATIC 0x01 //!< Static address +#define ADDRTYPE_PRIVATE_NONRESOLVE 0x02 //!< Generate Non-Resolvable Private Address +#define ADDRTYPE_PRIVATE_RESOLVE 0x03 //!< Generate Resolvable Private Address + +// GAP_ADVERTISEMENT_TYPE_DEFINES GAP Advertising Event Types +#define GAP_ADTYPE_ADV_IND 0x00 //!< Connectable undirected event typet +#define GAP_ADTYPE_ADV_HDC_DIRECT_IND 0x01 //!< Connectable high duty cycle directed event type +#define GAP_ADTYPE_ADV_SCAN_IND 0x02 //!< Scannable undirected event type +#define GAP_ADTYPE_ADV_NONCONN_IND 0x03 //!< Non-Connectable undirected event type +#define GAP_ADTYPE_ADV_LDC_DIRECT_IND 0x04 //!< Connectable low duty cycle directed event type +//v5.x +#define GAP_ADTYPE_EXT_CONN_DIRECT 0x05 //!< extend Connectable directed event type +#define GAP_ADTYPE_EXT_SCAN_UNDIRECT 0x06 //!< extend Scannable undirected event type +#define GAP_ADTYPE_EXT_NONCONN_NONSCAN_UNDIRECT 0x07 //!< extend Non-Connectable and Non-Scannable undirected event type +#define GAP_ADTYPE_EXT_CONN_UNDIRECT 0x08 //!< extend Connectable undirected event type +#define GAP_ADTYPE_EXT_SCAN_DIRECT 0x09 //!< extend Scannable directed event type +#define GAP_ADTYPE_EXT_NONCONN_NONSCAN_DIRECT 0x0A //!< extend Non-Connectable and Non-Scannable directed event type + +// GAP_ADVERTISEMENT_TYPE_DEFINES GAP Advertising PHY VAL TYPE(GAP_PHY_VAL_TYPE) +#define GAP_PHY_VAL_TYPE +#define GAP_PHY_VAL_LE_1M 0x01 +#define GAP_PHY_VAL_LE_2M 0x02 +#define GAP_PHY_VAL_LE_CODED 0x03 + +// GAP_ADVERTISEMENT_TYPE_DEFINES GAP Scan PHY VAL TYPE(GAP_PHY_BIT_TYPE) +#define GAP_PHY_BIT_TYPE +#define GAP_PHY_BIT_LE_1M (1<<0) +#define GAP_PHY_BIT_LE_2M (1<<1) +#define GAP_PHY_BIT_LE_CODED (1<<2) +#define GAP_PHY_BIT_ALL (GAP_PHY_BIT_LE_1M|GAP_PHY_BIT_LE_2M|GAP_PHY_BIT_LE_CODED) +#define GAP_PHY_BIT_LE_CODED_S2 (1<<3) + +// PHY_OPTIONS preferred coding when transmitting on the LE Coded PHY +#define GAP_PHY_OPTIONS_TYPE +#define GAP_PHY_OPTIONS_NOPRE 0x00 // 0:no preferred +#define GAP_PHY_OPTIONS_S2 0x01 +#define GAP_PHY_OPTIONS_S8 0x02 + +// GAP_ADVERTISEMENT_TYPE_DEFINES GAP Periodic Advertising Properties +#define GAP_PERI_PROPERTIES_INCLUDE_TXPOWER (1<<6) + +// GAP Advertising Report Event Types +#define GAP_ADVERTISEMENT_REPORT_TYPE_DEFINES +// bit0 to 4 ADVERTISEMENT_TYPE:defined for gapExtAdvDeviceInfoEvent_t Advertisement data type +#define GAP_ADRPT_ADV_IND 0x00 //!< Connectable undirected advertisement +#define GAP_ADRPT_ADV_DIRECT_IND 0x01 //!< Connectable directed advertisement +#define GAP_ADRPT_ADV_SCAN_IND 0x02 //!< Scannable undirected advertisement +#define GAP_ADRPT_ADV_NONCONN_IND 0x03 //!< Non-Connectable undirected advertisement +#define GAP_ADRPT_SCAN_RSP 0x04 //!< Scan Response +#define GAP_ADRPT_EXT_CONN_DIRECT 0x05 //!< extend Connectable directed report type +#define GAP_ADRPT_EXT_SCAN_UNDIRECT 0x06 //!< extend Scannable undirected report type +#define GAP_ADRPT_EXT_NONCONN_NONSCAN_UNDIRECT 0x07 //!< extend Non-Connectable and Non-Scannable undirected report type +#define GAP_ADRPT_EXT_CONN_UNDIRECT 0x08 //!< extend Connectable undirected report type +#define GAP_ADRPT_EXT_SCAN_DIRECT 0x09 //!< extend Scannable directed report type +#define GAP_ADRPT_EXT_NONCONN_NONSCAN_DIRECT 0x0A //!< extend Non-Connectable and Non-Scannable directed report type +#define GAP_ADRPT_EXT_SCAN_RESPONSE 0x0B //!< extend Scan Response report type +// bit5 to 6 Data status:defined for gapExtAdvDeviceInfoEvent_t Advertisement data type +#define GAP_ADRPT_EXT_DATA_MASK (3<<5) +#define GAP_ADRPT_EXT_DATA_COMPLETE (0<<5) //!< Complete +#define GAP_ADRPT_EXT_DATA_INCOMPLETE (1<<5) //!< more data to come +#define GAP_ADRPT_EXT_DATA_LAST (2<<5) //!< Incomplete, data truncated, no more to come + +// GAP_EXTEND_ADVERTISEMENT_REPORT_TYPE_DEFINES GAP Extend Advertising Report Event Types +#define GAP_ADRPT_ADV_CONNECTABLE (1<<0) +#define GAP_ADRPT_ADV_SCANNABLE (1<<1) +#define GAP_ADRPT_ADV_DITECTED (1<<2) +#define GAP_ADRPT_SCAN_RESPONSE (1<<3) + +// GAP_FILTER_POLICY_DEFINES GAP Advertiser Filter Scan Parameters +#define GAP_FILTER_POLICY_ALL 0x00 //!< Allow Scan Request from Any, Allow Connect Request from Any (default). +#define GAP_FILTER_POLICY_WHITE_SCAN 0x01 //!< Allow Scan Request from White List Only, Allow Connect from Any +#define GAP_FILTER_POLICY_WHITE_CON 0x02 //!< Allow Scan Request from Any, Connect from White List Only +#define GAP_FILTER_POLICY_WHITE 0x03 //!< Allow Scan Request and Connect from White List Only + +//! Maximum Pairing Passcode/Passkey value. Range of a passkey can be 0 - 999,999. +#define GAP_PASSCODE_MAX 999999 + +/** Sign Counter Initialized - Sign counter hasn't been used yet. Used when setting up + * a connection's signing information. + */ +#define GAP_INIT_SIGN_COUNTER 0xFFFFFFFF + +// GAP_ADVCHAN_DEFINES GAP Advertisement Channel Map +#define GAP_ADVCHAN_37 0x01 //!< Advertisement Channel 37 +#define GAP_ADVCHAN_38 0x02 //!< Advertisement Channel 38 +#define GAP_ADVCHAN_39 0x04 //!< Advertisement Channel 39 +#define GAP_ADVCHAN_ALL (GAP_ADVCHAN_37 | GAP_ADVCHAN_38 | GAP_ADVCHAN_39) //!< All Advertisement Channels Enabled + +// GAP_ADTYPE_DEFINES GAP Advertisement Data Types +#define GAP_ADTYPE_FLAGS 0x01 //!< Discovery Mode: @ref GAP_ADTYPE_FLAGS_MODES +#define GAP_ADTYPE_16BIT_MORE 0x02 //!< Service: More 16-bit UUIDs available +#define GAP_ADTYPE_16BIT_COMPLETE 0x03 //!< Service: Complete list of 16-bit UUIDs +#define GAP_ADTYPE_32BIT_MORE 0x04 //!< Service: More 32-bit UUIDs available +#define GAP_ADTYPE_32BIT_COMPLETE 0x05 //!< Service: Complete list of 32-bit UUIDs +#define GAP_ADTYPE_128BIT_MORE 0x06 //!< Service: More 128-bit UUIDs available +#define GAP_ADTYPE_128BIT_COMPLETE 0x07 //!< Service: Complete list of 128-bit UUIDs +#define GAP_ADTYPE_LOCAL_NAME_SHORT 0x08 //!< Shortened local name +#define GAP_ADTYPE_LOCAL_NAME_COMPLETE 0x09 //!< Complete local name +#define GAP_ADTYPE_POWER_LEVEL 0x0A //!< TX Power Level: -127 to +127 dBm +#define GAP_ADTYPE_OOB_CLASS_OF_DEVICE 0x0D //!< Simple Pairing OOB Tag: Class of device (3 octets) +#define GAP_ADTYPE_OOB_SIMPLE_PAIRING_HASHC 0x0E //!< Simple Pairing OOB Tag: Simple Pairing Hash C (16 octets) +#define GAP_ADTYPE_OOB_SIMPLE_PAIRING_RANDR 0x0F //!< Simple Pairing OOB Tag: Simple Pairing Randomizer R (16 octets) +#define GAP_ADTYPE_SM_TK 0x10 //!< Security Manager TK Value +#define GAP_ADTYPE_SM_OOB_FLAG 0x11 //!< Security Manager OOB Flags +#define GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE 0x12 //!< Min and Max values of the connection interval (2 octets Min, 2 octets Max) (0xFFFF indicates no conn interval min or max) +#define GAP_ADTYPE_SIGNED_DATA 0x13 //!< Signed Data field +#define GAP_ADTYPE_SERVICES_LIST_16BIT 0x14 //!< Service Solicitation: list of 16-bit Service UUIDs +#define GAP_ADTYPE_SERVICES_LIST_128BIT 0x15 //!< Service Solicitation: list of 128-bit Service UUIDs +#define GAP_ADTYPE_SERVICE_DATA 0x16 //!< Service Data - 16-bit UUID +#define GAP_ADTYPE_PUBLIC_TARGET_ADDR 0x17 //!< Public Target Address +#define GAP_ADTYPE_RANDOM_TARGET_ADDR 0x18 //!< Random Target Address +#define GAP_ADTYPE_APPEARANCE 0x19 //!< Appearance +#define GAP_ADTYPE_ADV_INTERVAL 0x1A //!< Advertising Interval +#define GAP_ADTYPE_LE_BD_ADDR 0x1B //!< LE Bluetooth Device Address +#define GAP_ADTYPE_LE_ROLE 0x1C //!< LE Role +#define GAP_ADTYPE_SIMPLE_PAIRING_HASHC_256 0x1D //!< Simple Pairing Hash C-256 +#define GAP_ADTYPE_SIMPLE_PAIRING_RANDR_256 0x1E //!< Simple Pairing Randomizer R-256 +#define GAP_ADTYPE_SERVICE_DATA_32BIT 0x20 //!< Service Data - 32-bit UUID +#define GAP_ADTYPE_SERVICE_DATA_128BIT 0x21 //!< Service Data - 128-bit UUID +#define GAP_ADTYPE_URI 0x24 //!< URI +#define GAP_ADTYPE_INDOOR_POSITION 0x25 //!< Indoor Positioning Service v1.0 or later +#define GAP_ADTYPE_TRAN_DISCOVERY_DATA 0x26 //!< Transport Discovery Service v1.0 or later +#define GAP_ADTYPE_SUPPORTED_FEATURES 0x27 //!< LE Supported Features +#define GAP_ADTYPE_CHANNEL_MAP_UPDATE 0x28 //!< Channel Map Update Indication +#define GAP_ADTYPE_PB_ADV 0x29 //!< PB-ADV. Mesh Profile Specification Section 5.2.1 +#define GAP_ADTYPE_MESH_MESSAGE 0x2A //!< Mesh Message. Mesh Profile Specification Section 3.3.1 +#define GAP_ADTYPE_MESH_BEACON 0x2B //!< Mesh Beacon. Mesh Profile Specification Section 3.9 +#define GAP_ADTYPE_BIG_INFO 0x2C //!< BIGInfo +#define GAP_ADTYPE_BROADCAST_CODE 0x2D //!< Broadcast_Code +#define GAP_ADTYPE_RSL_SET_IDENT 0x2E //!< Resolvable Set Identifier.Coordinated Set Identification Profile 1.0 +#define GAP_ADTYPE_ADV_INTERVAL_LONG 0x2F //!< Advertising Interval - long +#define GAP_ADTYPE_3D_INFO_DATA 0x3D //!< 3D Information Data +#define GAP_ADTYPE_MANUFACTURER_SPECIFIC 0xFF //!< Manufacturer Specific Data: first 2 octets contain the Company Identifier Code followed by the additional manufacturer specific data + +// GAP_ADTYPE_FLAGS_MODES GAP ADTYPE Flags Discovery Modes +#define GAP_ADTYPE_FLAGS_LIMITED 0x01 //!< Discovery Mode: LE Limited Discoverable Mode +#define GAP_ADTYPE_FLAGS_GENERAL 0x02 //!< Discovery Mode: LE General Discoverable Mode +#define GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED 0x04 //!< Discovery Mode: BR/EDR Not Supported + +// GAP_APPEARANCE_VALUES GAP Appearance Values +#define GAP_APPEARE_UNKNOWN 0x0000 //!< Unknown +#define GAP_APPEARE_GENERIC_PHONE 0x0040 //!< Generic Phone +#define GAP_APPEARE_GENERIC_COMPUTER 0x0080 //!< Generic Computer +#define GAP_APPEARE_GENERIC_WATCH 0x00C0 //!< Generic Watch +#define GAP_APPEARE_WATCH_SPORTS 0x00C1 //!< Watch: Sports Watch +#define GAP_APPEARE_GENERIC_CLOCK 0x0100 //!< Generic Clock +#define GAP_APPEARE_GENERIC_DISPLAY 0x0140 //!< Generic Display +#define GAP_APPEARE_GENERIC_RC 0x0180 //!< Generic Remote Control +#define GAP_APPEARE_GENERIC_EYE_GALSSES 0x01C0 //!< Generic Eye-glasses +#define GAP_APPEARE_GENERIC_TAG 0x0200 //!< Generic Tag +#define GAP_APPEARE_GENERIC_KEYRING 0x0240 //!< Generic Keyring +#define GAP_APPEARE_GENERIC_MEDIA_PLAYER 0x0280 //!< Generic Media Player +#define GAP_APPEARE_GENERIC_BARCODE_SCANNER 0x02C0 //!< Generic Barcode Scanner +#define GAP_APPEARE_GENERIC_THERMOMETER 0x0300 //!< Generic Thermometer +#define GAP_APPEARE_GENERIC_THERMO_EAR 0x0301 //!< Thermometer: Ear +#define GAP_APPEARE_GENERIC_HR_SENSOR 0x0340 //!< Generic Heart rate Sensor +#define GAP_APPEARE_GENERIC_HRS_BELT 0x0341 //!< Heart Rate Sensor: Heart Rate Belt +#define GAP_APPEARE_GENERIC_BLOOD_PRESSURE 0x0380 //!< Generic Blood Pressure +#define GAP_APPEARE_GENERIC_BP_ARM 0x0381 //!< Blood Pressure: Arm +#define GAP_APPEARE_GENERIC_BP_WRIST 0x0382 //!< Blood Pressure: Wrist +#define GAP_APPEARE_GENERIC_HID 0x03C0 //!< Generic Human Interface Device (HID) +#define GAP_APPEARE_HID_KEYBOARD 0x03C1 //!< HID Keyboard +#define GAP_APPEARE_HID_MOUSE 0x03C2 //!< HID Mouse +#define GAP_APPEARE_HID_JOYSTIC 0x03C3 //!< HID Joystick +#define GAP_APPEARE_HID_GAMEPAD 0x03C4 //!< HID Gamepad +#define GAP_APPEARE_HID_DIGITIZER_TYABLET 0x03C5 //!< HID Digitizer Tablet +#define GAP_APPEARE_HID_DIGITAL_CARDREADER 0x03C6 //!< HID Card Reader +#define GAP_APPEARE_HID_DIGITAL_PEN 0x03C7 //!< HID Digital Pen +#define GAP_APPEARE_HID_BARCODE_SCANNER 0x03C8 //!< HID Barcode Scanner + +/************************************gapRole***********************************/ +// GAPROLE_PROFILE_PARAMETERS GAP Role Manager Parameters +#define GAPROLE_PROFILEROLE 0x300 //!< Reading this parameter will return GAP Role type. Read Only. Size is uint8_t. +#define GAPROLE_IRK 0x301 //!< Identity Resolving Key. Read/Write. Size is uint8_t[KEYLEN]. Default is all 0, which means that the IRK will be randomly generated. +#define GAPROLE_SRK 0x302 //!< Signature Resolving Key. Read/Write. Size is uint8_t[KEYLEN]. Default is all 0, which means that the SRK will be randomly generated. +#define GAPROLE_SIGNCOUNTER 0x303 //!< Sign Counter. Read/Write. Size is uint32_t. Default is 0. +#define GAPROLE_BD_ADDR 0x304 //!< Device's Address. Read Only. Size is uint8_t[B_ADDR_LEN]. This item is read from the controller. +#define GAPROLE_ADVERT_ENABLED 0x305 //!< Enable/Disable Advertising. Read/Write. Size is uint8_t. Default is TRUE=Enabled. +#define GAPROLE_ADVERT_DATA 0x306 //!< Advertisement Data. Read/Write. Max size is B_MAX_ADV_EXT_LEN. Default to all 0. +#define GAPROLE_SCAN_RSP_DATA 0x307 //!< Scan Response Data. Read/Write. Max size is B_MAX_ADV_EXT_LEN. Defaults to all 0. +#define GAPROLE_ADV_EVENT_TYPE 0x308 //!< Advertisement Type. Read/Write. Size is uint8_t. Default is GAP_ADTYPE_ADV_IND. +#define GAPROLE_ADV_DIRECT_TYPE 0x309 //!< Direct Advertisement Address Type. Read/Write. Size is uint8_t. Default is ADDRTYPE_PUBLIC. +#define GAPROLE_ADV_DIRECT_ADDR 0x30A //!< Direct Advertisement Address. Read/Write. Size is uint8_t[B_ADDR_LEN]. Default is NULL. +#define GAPROLE_ADV_CHANNEL_MAP 0x30B //!< Which channels to advertise on. Read/Write Size is uint8_t. Default is GAP_ADVCHAN_ALL +#define GAPROLE_ADV_FILTER_POLICY 0x30C //!< Filter Policy. Ignored when directed advertising is used. Read/Write. Size is uint8_t. Default is GAP_FILTER_POLICY_ALL. +#define GAPROLE_STATE 0x30D //!< Reading this parameter will return GAP Peripheral Role State. Read Only. Size is uint8_t. +#define GAPROLE_MAX_SCAN_RES 0x30E //!< Maximum number of discover scan results to receive. Default is 0 = unlimited. +#define GAPROLE_MIN_CONN_INTERVAL 0x311 //!< Minimum Connection Interval to allow (n * 1.25ms). Range: 7.5 msec to 4 seconds (0x0006 to 0x0C80). Read/Write. Size is uint16_t. Default is 7.5 milliseconds (0x0006). +#define GAPROLE_MAX_CONN_INTERVAL 0x312 //!< Maximum Connection Interval to allow (n * 1.25ms). Range: 7.5 msec to 4 seconds (0x0006 to 0x0C80). Read/Write. Size is uint16_t. Default is 4 seconds (0x0C80). +// v5.x +#define GAPROLE_PHY_TX_SUPPORTED 0x313 //!< The transmitter PHYs that the Host prefers the Controller to use.Default is GAP_PHY_BIT_ALL +#define GAPROLE_PHY_RX_SUPPORTED 0x314 //!< The receiver PHYs that the Host prefers the Controller to use.Default is GAP_PHY_BIT_ALL +#define GAPROLE_PERIODIC_ADVERT_DATA 0x315 //!< Periodic advertisement Data. Read/Write. Max size is B_MAX_ADV_PERIODIC_LEN. Default to all 0. +#define GAPROLE_PERIODIC_ADVERT_ENABLED 0x316 //!< bit0:Enable/Disable Periodic Advertising. Read/Write. Size is uint8_t. Default is FALSE=Disable. + //!< bit1:Include the ADI field in AUX_SYNC_IND PDUs + +/************************************GAPBOND***********************************/ +// GAPBOND_PROFILE_PARAMETERS GAP Bond Manager Parameters +#define GAPBOND_PERI_PAIRING_MODE 0x400 //!< Pairing Mode: @ref GAPBOND_PAIRING_MODE_DEFINES. Read/Write. Size is uint8_t. Default is GAPBOND_PAIRING_MODE_WAIT_FOR_REQ. +#define GAPBOND_PERI_MITM_PROTECTION 0x401 //!< Man-In-The-Middle (MITM) basically turns on Passkey protection in the pairing algorithm. Read/Write. Size is uint8_t. Default is 0(disabled). +#define GAPBOND_PERI_IO_CAPABILITIES 0x402 //!< I/O capabilities. Read/Write. Size is uint8_t. Default is GAPBOND_IO_CAP_DISPLAY_ONLY @ref GAPBOND_IO_CAP_DEFINES. +#define GAPBOND_PERI_OOB_ENABLED 0x403 //!< OOB data available for pairing algorithm. Read/Write. Size is uint8_t. Default is 0(disabled). +#define GAPBOND_PERI_OOB_DATA 0x404 //!< OOB Data. Read/Write. size uint8_t[16]. Default is all 0's. +#define GAPBOND_PERI_BONDING_ENABLED 0x405 //!< Request Bonding during the pairing process if enabled. Read/Write. Size is uint8_t. Default is 0(disabled). +#define GAPBOND_PERI_KEY_DIST_LIST 0x406 //!< The key distribution list for bonding. size is uint8_t. @ref GAPBOND_KEY_DIST_DEFINES. Default is 0x77. +#define GAPBOND_PERI_DEFAULT_PASSCODE 0x407 //!< The default passcode for MITM protection. size is uint32_t. Range is 0 - 999,999. Default is 0. +#define GAPBOND_CENT_PAIRING_MODE 0x408 //!< Pairing Mode: @ref GAPBOND_PAIRING_MODE_DEFINES. Read/Write. Size is uint8_t. Default is GAPBOND_PAIRING_MODE_WAIT_FOR_REQ. +#define GAPBOND_CENT_MITM_PROTECTION 0x409 //!< Man-In-The-Middle (MITM) basically turns on Passkey protection in the pairing algorithm. Read/Write. Size is uint8_t. Default is 0(disabled). +#define GAPBOND_CENT_IO_CAPABILITIES 0x40A //!< I/O capabilities. Read/Write. Size is uint8_t. Default is GAPBOND_IO_CAP_DISPLAY_ONLY @ref GAPBOND_IO_CAP_DEFINES. +#define GAPBOND_CENT_OOB_ENABLED 0x40B //!< OOB data available for pairing algorithm. Read/Write. Size is uint8_t. Default is 0(disabled). +#define GAPBOND_CENT_OOB_DATA 0x40C //!< OOB Data. Read/Write. size uint8_t[16]. Default is all 0's. +#define GAPBOND_CENT_BONDING_ENABLED 0x40D //!< Request Bonding during the pairing process if enabled. Read/Write. Size is uint8_t. Default is 0(disabled). +#define GAPBOND_CENT_KEY_DIST_LIST 0x40E //!< The key distribution list for bonding. size is uint8_t. @ref GAPBOND_KEY_DIST_DEFINES. Default is 0x77. +#define GAPBOND_CENT_DEFAULT_PASSCODE 0x40F //!< The default passcode for MITM protection. size is uint32_t. Range is 0 - 999,999. Default is 0. +#define GAPBOND_ERASE_ALLBONDS 0x410 //!< Erase all of the bonded devices. Write Only. No Size. +#define GAPBOND_AUTO_FAIL_PAIRING 0x411 //!< TEST MODE (DO NOT USE) to automatically send a Pairing Fail when a Pairing Request is received. Read/Write. size is uint8_t. Default is 0 (disabled). +#define GAPBOND_AUTO_FAIL_REASON 0x412 //!< TEST MODE (DO NOT USE) Pairing Fail reason when auto failing. Read/Write. size is uint8_t. Default is 0x05 (SMP_PAIRING_FAILED_NOT_SUPPORTED). +#define GAPBOND_KEYSIZE 0x413 //!< Key Size used in pairing. Read/Write. size is uint8_t. Default is 16. +#define GAPBOND_AUTO_SYNC_WL 0x414 //!< Clears the White List adds to it each unique address stored by bonds in NV. Read/Write. Size is uint8_t. Default is FALSE. +#define GAPBOND_BOND_COUNT 0x415 //!< Gets the total number of bonds stored in NV. Read Only. Size is uint8_t. Default is 0 (no bonds). +#define GAPBOND_BOND_FAIL_ACTION 0x416 //!< Possible actions Central may take upon an unsuccessful bonding. Write Only. Size is uint8_t. Default is 0x02 (Terminate link upon unsuccessful bonding). +#define GAPBOND_ERASE_SINGLEBOND 0x417 //!< Erase a single bonded device. Write only. Must provide address type followed by device address. +#define GAPBOND_BOND_AUTO 0x418 //!< Auto save bonds into FLASH. Write Only. size is uint8_t. Default is 1(enabled). +#define GAPBOND_BOND_UPDATE 0x419 //!< Save current bonds into FLASH. Write Only. No Size. +#define GAPBOND_DISABLE_SINGLEBOND 0x41A //!< Disable a single bonded device. Write only. Must provide address type followed by device address. +#define GAPBOND_ENABLE_SINGLEBOND 0x41B //!< Ensable a single bonded device. Write only. Must provide address type followed by device address. +#define GAPBOND_DISABLE_ALLBONDS 0x41C //!< Disable all of the bonded devices. Write Only. No Size. +#define GAPBOND_ENABLE_ALLBONDS 0x41D //!< Ensable all of the bonded devices. Write Only. No Size. +#define GAPBOND_ERASE_AUTO 0x41E //!< Auto erase all of the bonded devices when the maximum number is reached.Size is uint8_t. Default is 1(enabled). +#define GAPBOND_AUTO_SYNC_RL 0x41F //!< Clears the Resolving List adds to it each unique address stored by bonds in NV. Read/Write. Size is uint8_t. Default is FALSE. +#define GAPBOND_SET_ENC_PARAMS 0x420 //!< Set bonding parameters.size is bondEncParams_t. +#define GAPBOND_PERI_SC_PROTECTION 0x421 //!< Set peripheral sc enable. Default is FALSE. +#define GAPBOND_CENT_SC_PROTECTION 0x422 //!< Set central sc enable. Default is FALSE. + +// GAPBOND_PAIRING_MODE_DEFINES GAP Bond Manager Pairing Modes +#define GAPBOND_PAIRING_MODE_NO_PAIRING 0x00 //!< Pairing is not allowed +#define GAPBOND_PAIRING_MODE_WAIT_FOR_REQ 0x01 //!< Wait for a pairing request or slave security request +#define GAPBOND_PAIRING_MODE_INITIATE 0x02 //!< Don't wait, initiate a pairing request or slave security request + +// GAPBOND_IO_CAP_DEFINES GAP Bond Manager I/O Capabilities +#define GAPBOND_IO_CAP_DISPLAY_ONLY 0x00 //!< Display Only Device +#define GAPBOND_IO_CAP_DISPLAY_YES_NO 0x01 //!< Display and Yes and No Capable +#define GAPBOND_IO_CAP_KEYBOARD_ONLY 0x02 //!< Keyboard Only +#define GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT 0x03 //!< No Display or Input Device +#define GAPBOND_IO_CAP_KEYBOARD_DISPLAY 0x04 //!< Both Keyboard and Display Capable + +// GAPBOND_KEY_DIST_DEFINES GAP Bond Manager Key Distribution +#define GAPBOND_KEYDIST_SENCKEY 0x01 //!< Slave Encryption Key +#define GAPBOND_KEYDIST_SIDKEY 0x02 //!< Slave IRK and ID information +#define GAPBOND_KEYDIST_SSIGN 0x04 //!< Slave CSRK +#define GAPBOND_KEYDIST_SLINK 0x08 //!< Slave Link Key +#define GAPBOND_KEYDIST_MENCKEY 0x10 //!< Master Encrypton Key +#define GAPBOND_KEYDIST_MIDKEY 0x20 //!< Master IRK and ID information +#define GAPBOND_KEYDIST_MSIGN 0x40 //!< Master CSRK +#define GAPBOND_KEYDIST_MLINK 0x80 //!< Master Link Key + +// GAPBOND_PAIRING_STATE_DEFINES GAP Bond Manager Pairing States +#define GAPBOND_PAIRING_STATE_STARTED 0x00 //!< Pairing started +#define GAPBOND_PAIRING_STATE_COMPLETE 0x01 //!< Pairing complete +#define GAPBOND_PAIRING_STATE_BONDED 0x02 //!< Devices bonded +#define GAPBOND_PAIRING_STATE_BOND_SAVED 0x03 //!< Bonding record saved in NV + +// SMP_PAIRING_FAILED_DEFINES Pairing failure status values +#define SMP_PAIRING_FAILED_PASSKEY_ENTRY_FAILED 0x01 //!< The user input of the passkey failed, for example, the user cancelled the operation. +#define SMP_PAIRING_FAILED_OOB_NOT_AVAIL 0x02 //!< The OOB data is not available +#define SMP_PAIRING_FAILED_AUTH_REQ 0x03 //!< The pairing procedure can't be performed as authentication requirements can't be met due to IO capabilities of one or both devices +#define SMP_PAIRING_FAILED_CONFIRM_VALUE 0x04 //!< The confirm value doesn't match the calculated compare value +#define SMP_PAIRING_FAILED_NOT_SUPPORTED 0x05 //!< Pairing isn't supported by the device +#define SMP_PAIRING_FAILED_ENC_KEY_SIZE 0x06 //!< The resultant encryption key size is insufficient for the security requirements of this device. +#define SMP_PAIRING_FAILED_CMD_NOT_SUPPORTED 0x07 //!< The SMP command received is not supported on this device. +#define SMP_PAIRING_FAILED_UNSPECIFIED 0x08 //!< Pairing failed due to an unspecified reason +#define SMP_PAIRING_FAILED_REPEATED_ATTEMPTS 0x09 //!< Pairing or authentication procedure is disallowed because too little time has elapsed since the last pairing request or security request. +#define SMP_PAIRING_FAILED_INVALID_PARAMERERS 0x0A //!< The Invalid Parameters error code indicates that the command length is invalid or that a parameter is outside of the specified range. +#define SMP_PAIRING_FAILED_DHKEY_CHECK_FAILED 0x0B //!< Indicates to the remote device that the DHKey Check value received doesn��t match the one calculated by the local device. +#define SMP_PAIRING_FAILED_NUMERIC_COMPARISON 0x0C //!< Indicates that the confirm values in the numeric comparison protocol do not match. +#define SMP_PAIRING_FAILED_KEY_REJECTED 0x0F //!< Indicates that the device chose not to accept a distributed key. + +// GAPBOND_BONDING_FAILURE_DEFINES Bonding Failure Actions +#define GAPBOND_FAIL_NO_ACTION 0x00 //!< Take no action upon unsuccessful bonding +#define GAPBOND_FAIL_INITIATE_PAIRING 0x01 //!< Initiate pairing upon unsuccessful bonding +#define GAPBOND_FAIL_TERMINATE_LINK 0x02 //!< Terminate link upon unsuccessful bonding +#define GAPBOND_FAIL_TERMINATE_ERASE_BONDS 0x03 //!< Terminate link and erase all existing bonds on device upon unsuccessful bonding + +// Device NV Items +#define BLE_NVID_IRK 0x02 //!< The Device's IRK +#define BLE_NVID_CSRK 0x03 //!< The Device's CSRK +#define BLE_NVID_SIGNCOUNTER 0x04 //!< The Device's Sign Counter + +//!< RF Mode BOND NV IDs +#define BLE_NVID_BOND_RF_START 0x10 //!< Start of the RF BOND NV IDs + +// Bonding NV Items - Range 0x20 - 0x6F +#define BLE_NVID_GAP_BOND_START 0x20 //!< Start of the GAP Bond Manager's NV IDs + +// GAP BOND Items +#define GAP_BOND_REC_ID_OFFSET 0 //!< NV ID for the main bonding record +#define GAP_BOND_LOCAL_LTK_OFFSET 1 //!< NV ID for the bonding record's local LTK information +#define GAP_BOND_DEV_LTK_OFFSET 2 //!< NV ID for the bonding records' device LTK information +#define GAP_BOND_DEV_IRK_OFFSET 3 //!< NV ID for the bonding records' device IRK +#define GAP_BOND_DEV_CSRK_OFFSET 4 //!< NV ID for the bonding records' device CSRK +#define GAP_BOND_DEV_SIGN_COUNTER_OFFSET 5 //!< NV ID for the bonding records' device Sign Counter +#define GAP_BOND_REC_IDS 6 + +// Macros to calculate the index/offset in to NV space +#define calcNvID(Idx, offset) (((((Idx) * GAP_BOND_REC_IDS) + (offset))) + BLE_NVID_GAP_BOND_START) +#define mainRecordNvID(bondIdx) (calcNvID((bondIdx), GAP_BOND_REC_ID_OFFSET)) +#define localLTKNvID(bondIdx) (calcNvID((bondIdx), GAP_BOND_LOCAL_LTK_OFFSET)) +#define devLTKNvID(bondIdx) (calcNvID((bondIdx), GAP_BOND_DEV_LTK_OFFSET)) +#define devIRKNvID(bondIdx) (calcNvID((bondIdx), GAP_BOND_DEV_IRK_OFFSET)) +#define devCSRKNvID(bondIdx) (calcNvID((bondIdx), GAP_BOND_DEV_CSRK_OFFSET)) +#define devSignCounterNvID(bondIdx) (calcNvID((bondIdx), GAP_BOND_DEV_SIGN_COUNTER_OFFSET)) + +// GATT Configuration NV Items -Range 0x70 - 0x7F +#define BLE_NVID_GATT_CFG_START 0x70 //!< Start of the GATT Configuration NV IDs + +// Macros to calculate the GATT index/offset in to NV space +#define gattCfgNvID(Idx) ((Idx) + BLE_NVID_GATT_CFG_START) + +#define BLE_NVID_MAX_VAL 0x7F + +// Structure of NV data for the connected device's encryption information +typedef struct +{ + uint8_t LTK[KEYLEN]; // Long Term Key (LTK) + uint16_t div; // LTK eDiv + uint8_t rand[B_RANDOM_NUM_SIZE]; // LTK random number + uint8_t keySize; // LTK key size +} gapBondLTK_t; + +// Structure of NV data for the connected device's address information +typedef struct +{ + uint8_t publicAddr[B_ADDR_LEN]; // Master's address + uint8_t reconnectAddr[B_ADDR_LEN]; // Privacy Reconnection Address + uint16_t stateFlags; // State flags: SM_AUTH_STATE_AUTHENTICATED & SM_AUTH_STATE_BONDING + uint8_t bondsToDelete; +} gapBondRec_t; + +// Structure of NV data for the connected device's characteristic configuration +typedef struct +{ + uint16_t attrHandle; // attribute handle + uint8_t value; // attribute value for this device +} gapBondCharCfg_t; + +/********************************************************************* + * TYPEDEFS + */ +typedef struct +{ + uint8_t srk[KEYLEN]; // Signature Resolving Key + uint32_t signCounter; // Sign Counter +} linkSec_t; + +typedef struct +{ + uint8_t ltk[KEYLEN]; // Long Term Key + uint16_t div; // Diversifier + uint8_t rand[B_RANDOM_NUM_SIZE]; // random number + uint8_t keySize; // LTK Key Size + uint8_t gapBondInvalid; +} encParams_t; + +typedef struct +{ + uint8_t connRole; // GAP Profile Roles @GAP_PROFILE_ROLE_DEFINES + uint8_t addrType; // Address type of connected device + uint8_t addr[B_ADDR_LEN]; // Other Device's address + encParams_t encParams; +} bondEncParams_t; + +typedef struct +{ + uint8_t taskID; // Application that controls the link + uint16_t connectionHandle; // Controller connection handle + uint8_t stateFlags; // LINK_CONNECTED, LINK_AUTHENTICATED... + uint8_t addrType; // Address type of connected device + uint8_t addr[B_ADDR_LEN]; // Other Device's address + uint8_t connRole; // Connection formed as central or peripheral + uint16_t connInterval; // The connection's interval (n * 1.25ms) + uint16_t connLatency; + uint16_t connTimeout; + uint16_t MTU; // The connection's MTU size + linkSec_t sec; // Connection Security related items + encParams_t *pEncParams; // pointer to LTK, ediv, rand. if needed. + uint16_t smEvtID; + void *pPairingParams; + void *pAuthLink; +} linkDBItem_t; + +// function pointer used to register for a status callback +typedef void (*pfnLinkDBCB_t)( uint16_t connectionHandle, uint8_t changeType ); +// function pointer used to perform specialized link database searches +typedef void (*pfnPerformFuncCB_t)( linkDBItem_t *pLinkItem ); + +/** + * Attribute Type format (2 or 16 octet UUID). + */ +typedef struct +{ + uint8_t len; //!< Length of UUID (2 or 16) + uint8_t uuid[ATT_UUID_SIZE]; //!< 16 or 128 bit UUID +} attAttrType_t; + +/** + * Attribute Type format (2-octet Bluetooth UUID). + */ +typedef struct +{ + uint8_t len; //!< Length of UUID (2) + uint8_t uuid[ATT_BT_UUID_SIZE]; //!< 16 bit UUID +} attAttrBtType_t; + +/** + * Error Response format. + */ +typedef struct +{ + uint8_t reqOpcode; //!< Request that generated this error response + uint16_t handle; //!< Attribute handle that generated error response + uint8_t errCode; //!< Reason why the request has generated error response +} attErrorRsp_t; + +/** + * Exchange MTU Request format. + */ +typedef struct +{ + uint16_t clientRxMTU; //!< Client receive MTU size +} attExchangeMTUReq_t; + +/** + * Exchange MTU Response format. + */ +typedef struct +{ + uint16_t serverRxMTU; //!< Server receive MTU size +} attExchangeMTURsp_t; + +/** + * Find Information Request format. + */ +typedef struct +{ + uint16_t startHandle; //!< First requested handle number (must be first field) + uint16_t endHandle; //!< Last requested handle number +} attFindInfoReq_t; + +/** + * Find Information Response format. + */ +typedef struct +{ + uint16_t numInfo; //!< Number of attribute handle-UUID pairs found + uint8_t format; //!< Format of information data + uint8_t *pInfo; //!< Information data whose format is determined by format field (4 to ATT_MTU_SIZE-2) +} attFindInfoRsp_t; + +/** + * Find By Type Value Request format. + */ +typedef struct +{ + uint16_t startHandle; //!< First requested handle number (must be first field) + uint16_t endHandle; //!< Last requested handle number + attAttrBtType_t type; //!< 2-octet UUID to find + uint16_t len; //!< Length of value + uint8_t *pValue; //!< Attribute value to find (0 to ATT_MTU_SIZE-7) +} attFindByTypeValueReq_t; + +/** + * Find By Type Value Response format. + */ +typedef struct +{ + uint16_t numInfo; //!< Number of handles information found + uint8_t *pHandlesInfo; //!< List of 1 or more handles information (4 to ATT_MTU_SIZE-1) +} attFindByTypeValueRsp_t; + +/** + * Read By Type Request format. + */ +typedef struct +{ + uint16_t startHandle; //!< First requested handle number (must be first field) + uint16_t endHandle; //!< Last requested handle number + attAttrType_t type; //!< Requested type (2 or 16 octet UUID) +} attReadByTypeReq_t; + +/** + * Read By Type Response format. + */ +typedef struct +{ + uint16_t numPairs; //!< Number of attribute handle-UUID pairs found + uint16_t len; //!< Size of each attribute handle-value pair + uint8_t *pDataList; //!< List of 1 or more attribute handle-value pairs (2 to ATT_MTU_SIZE-2) +} attReadByTypeRsp_t; + +/** + * Read Request format. + */ +typedef struct +{ + uint16_t handle; //!< Handle of the attribute to be read (must be first field) +} attReadReq_t; + +/** + * Read Response format. + */ +typedef struct +{ + uint16_t len; //!< Length of value + uint8_t *pValue; //!< Value of the attribute with the handle given (0 to ATT_MTU_SIZE-1) +} attReadRsp_t; + +/** + * Read Blob Req format. + */ +typedef struct +{ + uint16_t handle; //!< Handle of the attribute to be read (must be first field) + uint16_t offset; //!< Offset of the first octet to be read +} attReadBlobReq_t; + +/** + * Read Blob Response format. + */ +typedef struct +{ + uint16_t len; //!< Length of value + uint8_t *pValue; //!< Part of the value of the attribute with the handle given (0 to ATT_MTU_SIZE-1) +} attReadBlobRsp_t; + +/** + * Read Multiple Request format. + */ +typedef struct +{ + uint8_t *pHandles; //!< Set of two or more attribute handles (4 to ATT_MTU_SIZE-1) - must be first field + uint16_t numHandles; //!< Number of attribute handles +} attReadMultiReq_t; + +/** + * Read Multiple Response format. + */ +typedef struct +{ + uint16_t len; //!< Length of values + uint8_t *pValues; //!< Set of two or more values (0 to ATT_MTU_SIZE-1) +} attReadMultiRsp_t; + +/** + * Read By Group Type Request format. + */ +typedef struct +{ + uint16_t startHandle; //!< First requested handle number (must be first field) + uint16_t endHandle; //!< Last requested handle number + attAttrType_t type; //!< Requested group type (2 or 16 octet UUID) +} attReadByGrpTypeReq_t; + +/** + * Read By Group Type Response format. + */ +typedef struct +{ + uint16_t numGrps; //!< Number of attribute handle, end group handle and value sets found + uint16_t len; //!< Length of each attribute handle, end group handle and value set + uint8_t *pDataList; //!< List of 1 or more attribute handle, end group handle and value (4 to ATT_MTU_SIZE-2) +} attReadByGrpTypeRsp_t; + +/** + * Write Request format. + */ +typedef struct +{ + uint16_t handle; //!< Handle of the attribute to be written (must be first field) + uint16_t len; //!< Length of value + uint8_t *pValue; //!< Value of the attribute to be written (0 to ATT_MTU_SIZE-3) + uint8_t sig; //!< Authentication Signature status (not included (0), valid (1), invalid (2)) + uint8_t cmd; //!< Command Flag +} attWriteReq_t; + +/** + * Prepare Write Request format. + */ +typedef struct +{ + uint16_t handle; //!< Handle of the attribute to be written (must be first field) + uint16_t offset; //!< Offset of the first octet to be written + uint16_t len; //!< Length of value + uint8_t *pValue; //!< Part of the value of the attribute to be written (0 to ATT_MTU_SIZE-5) - must be allocated +} attPrepareWriteReq_t; + +/** + * Prepare Write Response format. + */ +typedef struct +{ + uint16_t handle; //!< Handle of the attribute that has been read + uint16_t offset; //!< Offset of the first octet to be written + uint16_t len; //!< Length of value + uint8_t *pValue; //!< Part of the value of the attribute to be written (0 to ATT_MTU_SIZE-5) +} attPrepareWriteRsp_t; + +/** + * Execute Write Request format. + */ +typedef struct +{ + uint8_t flags; //!< 0x00 - cancel all prepared writes. + //!< 0x01 - immediately write all pending prepared values. +} attExecuteWriteReq_t; + +/** + * Handle Value Notification format. + */ +typedef struct +{ + uint16_t handle; //!< Handle of the attribute that has been changed (must be first field) + uint16_t len; //!< Length of value + uint8_t *pValue; //!< Current value of the attribute (0 to ATT_MTU_SIZE-3) +} attHandleValueNoti_t; + +/** + * Handle Value Indication format. + */ +typedef struct +{ + uint16_t handle; //!< Handle of the attribute that has been changed (must be first field) + uint16_t len; //!< Length of value + uint8_t *pValue; //!< Current value of the attribute (0 to ATT_MTU_SIZE-3) +} attHandleValueInd_t; + +/** + * ATT Flow Control Violated Event message format. This message is sent to the + * app by the local ATT Server or Client when a sequential ATT Request-Response + * or Indication-Confirmation protocol flow control is violated for a connection. + * All subsequent ATT Requests and Indications received by the local ATT Server + * and Client respectively will be dropped. + * + * This message is to inform the app (that has registered with GAP by calling + * GAP_RegisterForMsgs()) in case it wants to drop the connection. + */ +typedef struct +{ + uint8_t opcode; //!< opcode of message that caused flow control violation + uint8_t pendingOpcode; //!< opcode of pending message +} attFlowCtrlViolatedEvt_t; + +/** + * ATT MTU Updated Event message format. This message is sent to the app + * by the local ATT Server or Client when the ATT MTU size is updated for a + * connection. The default ATT MTU size is 23 octets. + * + * This message is to inform the app (that has registered with GAP by calling + * GAP_RegisterForMsgs()) about the new ATT MTU size negotiated for a connection. + */ +typedef struct +{ + uint16_t MTU; //!< new MTU size +} attMtuUpdatedEvt_t; + +/** + * ATT Message format. It's a union of all attribute protocol messages and + * locally-generated events used between the attribute protocol and upper + * layer profile/application. + */ +typedef union +{ + // Request messages + attExchangeMTUReq_t exchangeMTUReq; //!< ATT Exchange MTU Request + attFindInfoReq_t findInfoReq; //!< ATT Find Information Request + attFindByTypeValueReq_t findByTypeValueReq; //!< ATT Find By Type Value Request + attReadByTypeReq_t readByTypeReq; //!< ATT Read By Type Request + attReadReq_t readReq; //!< ATT Read Request + attReadBlobReq_t readBlobReq; //!< ATT Read Blob Request + attReadMultiReq_t readMultiReq; //!< ATT Read Multiple Request + attReadByGrpTypeReq_t readByGrpTypeReq; //!< ATT Read By Group Type Request + attWriteReq_t writeReq; //!< ATT Write Request + attPrepareWriteReq_t prepareWriteReq; //!< ATT Prepare Write Request + attExecuteWriteReq_t executeWriteReq; //!< ATT Execute Write Request + + // Response messages + attErrorRsp_t errorRsp; //!< ATT Error Response + attExchangeMTURsp_t exchangeMTURsp; //!< ATT Exchange MTU Response + attFindInfoRsp_t findInfoRsp; //!< ATT Find Information Response + attFindByTypeValueRsp_t findByTypeValueRsp; //!< ATT Find By Type Value Response + attReadByTypeRsp_t readByTypeRsp; //!< ATT Read By Type Response + attReadRsp_t readRsp; //!< ATT Read Response + attReadBlobRsp_t readBlobRsp; //!< ATT Read Blob Response + attReadMultiRsp_t readMultiRsp; //!< ATT Read Multiple Response + attReadByGrpTypeRsp_t readByGrpTypeRsp; //!< ATT Read By Group Type Response + attPrepareWriteRsp_t prepareWriteRsp; //!< ATT Prepare Write Response + + // Indication and Notification messages + attHandleValueNoti_t handleValueNoti; //!< ATT Handle Value Notification + attHandleValueInd_t handleValueInd; //!< ATT Handle Value Indication + + // Locally-generated event messages + attFlowCtrlViolatedEvt_t flowCtrlEvt; //!< ATT Flow Control Violated Event + attMtuUpdatedEvt_t mtuEvt; //!< ATT MTU Updated Event +} attMsg_t; + +/** + * GATT Find By Type Value Request format. + */ +typedef struct +{ + uint16_t startHandle; //!< First requested handle number (must be first field) + uint16_t endHandle; //!< Last requested handle number + attAttrType_t value; //!< Primary service UUID value (2 or 16 octets) +} gattFindByTypeValueReq_t; + +/** + * GATT Read By Type Request format. + */ +typedef struct +{ + uint8_t discCharsByUUID; //!< Whether this is a GATT Discover Characteristics by UUID sub-procedure + attReadByTypeReq_t req; //!< Read By Type Request +} gattReadByTypeReq_t; + +/** + * GATT Write Long Request format. Do not change the order of the members. + */ +typedef struct +{ + uint8_t reliable; //!< Whether reliable writes requested (always FALSE for Write Long) + attPrepareWriteReq_t req; //!< ATT Prepare Write Request + uint16_t lastOffset; //!< Offset of last Prepare Write Request sent +} gattWriteLongReq_t; + +/** + * GATT Reliable Writes Request format. Do not change the order of the members. + */ +typedef struct +{ + uint8_t reliable; //!< Whether reliable writes requested (always TRUE for Reliable Writes) + attPrepareWriteReq_t *pReqs; //!< Array of Prepare Write Requests (must be allocated) + uint8_t numReqs; //!< Number of Prepare Write Requests + uint8_t index; //!< Index of last Prepare Write Request sent + uint8_t flags; //!< 0x00 - cancel all prepared writes. + //!< 0x01 - immediately write all pending prepared values. +} gattReliableWritesReq_t; + +/** + * GATT Message format. It's a union of all attribute protocol/profile messages + * and locally-generated events used between the attribute protocol/profile and + * upper layer application. + */ +typedef union +{ + // Request messages + attExchangeMTUReq_t exchangeMTUReq; //!< ATT Exchange MTU Request + attFindInfoReq_t findInfoReq; //!< ATT Find Information Request + attFindByTypeValueReq_t findByTypeValueReq; //!< ATT Find By Type Value Request + attReadByTypeReq_t readByTypeReq; //!< ATT Read By Type Request + attReadReq_t readReq; //!< ATT Read Request + attReadBlobReq_t readBlobReq; //!< ATT Read Blob Request + attReadMultiReq_t readMultiReq; //!< ATT Read Multiple Request + attReadByGrpTypeReq_t readByGrpTypeReq; //!< ATT Read By Group Type Request + attWriteReq_t writeReq; //!< ATT Write Request + attPrepareWriteReq_t prepareWriteReq; //!< ATT Prepare Write Request + attExecuteWriteReq_t executeWriteReq; //!< ATT Execute Write Request + gattFindByTypeValueReq_t gattFindByTypeValueReq;//!< GATT Find By Type Value Request + gattReadByTypeReq_t gattReadByTypeReq; //!< GATT Read By Type Request + gattWriteLongReq_t gattWriteLongReq; //!< GATT Long Write Request + gattReliableWritesReq_t gattReliableWritesReq; //!< GATT Reliable Writes Request + + // Response messages + attErrorRsp_t errorRsp; //!< ATT Error Response + attExchangeMTURsp_t exchangeMTURsp; //!< ATT Exchange MTU Response + attFindInfoRsp_t findInfoRsp; //!< ATT Find Information Response + attFindByTypeValueRsp_t findByTypeValueRsp; //!< ATT Find By Type Value Response + attReadByTypeRsp_t readByTypeRsp; //!< ATT Read By Type Response + attReadRsp_t readRsp; //!< ATT Read Response + attReadBlobRsp_t readBlobRsp; //!< ATT Read Blob Response + attReadMultiRsp_t readMultiRsp; //!< ATT Read Multiple Response + attReadByGrpTypeRsp_t readByGrpTypeRsp; //!< ATT Read By Group Type Response + attPrepareWriteRsp_t prepareWriteRsp; //!< ATT Prepare Write Response + + // Indication and Notification messages + attHandleValueNoti_t handleValueNoti; //!< ATT Handle Value Notification + attHandleValueInd_t handleValueInd; //!< ATT Handle Value Indication + + // Locally-generated event messages + attFlowCtrlViolatedEvt_t flowCtrlEvt; //!< ATT Flow Control Violated Event + attMtuUpdatedEvt_t mtuEvt; //!< ATT MTU Updated Event +} gattMsg_t; + +/** + * GATT tmos GATT_MSG_EVENT message format. This message is used to forward an + * incoming attribute protocol/profile message up to upper layer application. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GATT_MSG_EVENT and status + uint16_t connHandle; //!< Connection message was received on + uint8_t method; //!< Type of message + gattMsg_t msg; //!< Attribute protocol/profile message +} gattMsgEvent_t; + +/** + * GATT Attribute Type format. + */ +typedef struct +{ + uint8_t len; //!< Length of UUID (2 or 16) + const uint8_t *uuid; //!< Pointer to UUID +} gattAttrType_t; + +/** + * GATT Attribute format. + */ +typedef struct attAttribute_t +{ + gattAttrType_t type; //!< Attribute type (2 or 16 octet UUIDs) + uint8_t permissions; //!< Attribute permissions + uint16_t handle; //!< Attribute handle - assigned internally by attribute server + uint8_t *pValue; //!< Attribute value - encoding of the octet array is defined in + //!< the applicable profile. The maximum length of an attribute + //!< value shall be 512 octets. +} gattAttribute_t; + +/** + * GATT Service format. + */ +typedef struct +{ + uint16_t numAttrs; //!< Number of attributes in attrs + uint8_t encKeySize; //!< Minimum encryption key size required by service (7-16 bytes) + + /** Array of attribute records. + * note: The list must start with a Service attribute followed by + * all attributes associated with this Service attribute. + */ + gattAttribute_t *attrs; +} gattService_t; + +/** + * @brief Callback function prototype to read an attribute value. + * + * @note blePending can be returned ONLY for the following + * read operations: + * - Read Request: ATT_READ_REQ + * - Read Blob Request: ATT_READ_BLOB_REQ + * + * @note If blePending is returned then it's the responsibility of the application to respond to + * ATT_READ_REQ and ATT_READ_BLOB_REQ message with ATT_READ_RSP and ATT_READ_BLOB_RSP + * message respectively. + * + * @note Payload 'pValue' used with ATT_READ_RSP and ATT_READ_BLOB_RSP must be allocated using GATT_bm_alloc(). + * + * @param connHandle - connection request was received on + * @param pAttr - pointer to attribute + * @param pValue - pointer to data to be read (to be returned) + * @param pLen - length of data (to be returned) + * @param offset - offset of the first octet to be read + * @param maxLen - maximum length of data to be read + * @param method - type of read message + * + * @return SUCCESS: Read was successfully.
+ * blePending: A response is pending for this client.
+ * Error, otherwise: ref ATT_ERR_CODE_DEFINES.
+ */ +typedef uint8_t (*pfnGATTReadAttrCB_t)( uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, + uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method ); + +/** + * @brief Callback function prototype to write an attribute value. + * + * @note blePending can be returned ONLY for the following + * write operations: + * - Write Request: ATT_WRITE_REQ + * - Write Command: ATT_WRITE_CMD + * - Write Long: ATT_EXECUTE_WRITE_REQ + * - Reliable Writes: Multiple ATT_PREPARE_WRITE_REQ followed by one final ATT_EXECUTE_WRITE_REQ + * + * @note If blePending is returned then it's the responsibility of the application to 1) respond to + * ATT_WRITE_REQ and ATT_EXECUTE_WRITE_REQ message with ATT_WRITE_RSP and ATT_EXECUTE_WRITE_RSP + * message respectively, and 2) free each request payload 'pValue' using BM_free(). + * + * @note Write Command (ATT_WRITE_CMD) does NOT require a response message. + * + * @param connHandle - connection request was received on + * @param pAttr - pointer to attribute + * @param pValue - pointer to data to be written + * @param pLen - length of data + * @param offset - offset of the first octet to be written + * @param method - type of write message + * + * @return SUCCESS: Write was successfully.
+ * blePending: A response is pending for this client.
+ * Error, otherwise: ref ATT_ERR_CODE_DEFINES.
+ */ +typedef uint8_t (*pfnGATTWriteAttrCB_t)( uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, + uint16_t len, uint16_t offset, uint8_t method ); + +/** + * @brief Callback function prototype to authorize a Read or Write operation + * on a given attribute. + * + * @param connHandle - connection request was received on + * @param pAttr - pointer to attribute + * @param opcode - request opcode (ATT_READ_REQ or ATT_WRITE_REQ) + * + * @return SUCCESS: Operation authorized.
+ * ATT_ERR_INSUFFICIENT_AUTHOR: Authorization required.
+ */ +typedef bStatus_t (*pfnGATTAuthorizeAttrCB_t)( uint16_t connHandle, gattAttribute_t *pAttr, + uint8_t opcode ); + +/** + * GATT Structure for Client Characteristic Configuration. + */ +typedef struct +{ + uint16_t connHandle; //!< Client connection handle + uint8_t value; //!< Characteristic configuration value for this client +} gattCharCfg_t; + +/** + * GATT Structure for service callback functions - must be setup by the application + * and used when GATTServApp_RegisterService() is called. + */ +typedef struct +{ + pfnGATTReadAttrCB_t pfnReadAttrCB; //!< Read callback function pointer + pfnGATTWriteAttrCB_t pfnWriteAttrCB; //!< Write callback function pointer + pfnGATTAuthorizeAttrCB_t pfnAuthorizeAttrCB; //!< Authorization callback function pointer +} gattServiceCBs_t; + +/*************************************gap**************************************/ +/** + * Connection parameters for the peripheral device. These numbers are used + * to compare against connection events and request connection parameter + * updates with the central. + */ +typedef struct +{ + uint16_t intervalMin; //!< Minimum value for the connection event (interval. 0x0006 - 0x0C80 * 1.25ms) + uint16_t intervalMax; //!< Maximum value for the connection event (interval. 0x0006 - 0x0C80 * 1.25ms) + uint16_t latency; //!< Number of LL latency connection events (0x0000 - 0x03e8) + uint16_t timeout; //!< Connection Timeout (0x000A - 0x0C80 * 10ms) +} gapPeriConnectParams_t; + +/** + * GAP event header format. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP type of command. Ref: @ref GAP_MSG_EVENT_DEFINES +} gapEventHdr_t; + +/** + * GAP_DEVICE_INIT_DONE_EVENT message format. This message is sent to the + * app when the Device Initialization is done [initiated by calling + * GAP_DeviceInit()]. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_DEVICE_INIT_DONE_EVENT + uint8_t devAddr[B_ADDR_LEN]; //!< Device's BD_ADDR + uint16_t dataPktLen; //!< HC_LE_Data_Packet_Length + uint8_t numDataPkts; //!< HC_Total_Num_LE_Data_Packets +} gapDeviceInitDoneEvent_t; + +/** + * GAP_SIGNATURE_UPDATED_EVENT message format. This message is sent to the + * app when the signature counter has changed. This message is to inform the + * application in case it wants to save it to be restored on reboot or reconnect. + * This message is sent to update a connection's signature counter and to update + * this device's signature counter. If devAddr == BD_ADDR, then this message pertains + * to this device. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_SIGNATURE_UPDATED_EVENT + uint8_t addrType; //!< Device's address type for devAddr + uint8_t devAddr[B_ADDR_LEN]; //!< Device's BD_ADDR, could be own address + uint32_t signCounter; //!< new Signed Counter +} gapSignUpdateEvent_t; + +/** + * GAP_DEVICE_INFO_EVENT message format. This message is sent to the + * app during a Device Discovery Request, when a new advertisement or scan + * response is received. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_DEVICE_INFO_EVENT + uint8_t eventType; //!< Advertisement Type: @ref GAP_ADVERTISEMENT_REPORT_TYPE_DEFINES + uint8_t addrType; //!< address type: @ref GAP_ADDR_TYPE_DEFINES + uint8_t addr[B_ADDR_LEN]; //!< Address of the advertisement or SCAN_RSP + int8_t rssi; //!< Advertisement or SCAN_RSP RSSI + uint8_t dataLen; //!< Length (in bytes) of the data field (evtData) + uint8_t *pEvtData; //!< Data field of advertisement or SCAN_RSP +} gapDeviceInfoEvent_t; + +/** + * GAP_DIRECT_DEVICE_INFO_EVENT message format. This message is sent to the + * app during a Device Discovery Request, when a new advertisement or scan + * response is received. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_DIRECT_DEVICE_INFO_EVENT + uint8_t eventType; //!< Advertisement Type: @ref GAP_ADVERTISEMENT_REPORT_TYPE_DEFINES + uint8_t addrType; //!< address type: @ref GAP_ADDR_TYPE_DEFINES + uint8_t addr[B_ADDR_LEN]; //!< Address of the advertisement or SCAN_RSP + uint8_t directAddrType; //!< public or random address type + uint8_t directAddr[B_ADDR_LEN]; //!< device address + int8_t rssi; //!< Advertisement or SCAN_RSP RSSI +} gapDirectDeviceInfoEvent_t; + +/** + * GAP_EXT_ADV_DEVICE_INFO_EVENT message format. This message is sent to the + * app during a Device Discovery Request, when a new advertisement or scan + * response is received. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_EXT_ADV_DEVICE_INFO_EVENT + uint8_t eventType; //!< Advertisement Type: @ref GAP_ADVERTISEMENT_REPORT_TYPE_DEFINES + uint8_t addrType; //!< address type: @ref GAP_ADDR_TYPE_DEFINES + uint8_t addr[B_ADDR_LEN]; //!< Address of the advertisement or SCAN_RSP + uint8_t primaryPHY; //!< Advertiser PHY on the primary advertising channel + uint8_t secondaryPHY; //!< Advertiser PHY on the secondary advertising channel + uint8_t advertisingSID; //!< Value of the Advertising SID subfield in the ADI field of the PDU + int8_t txPower; //!< Advertisement or SCAN_RSP power + int8_t rssi; //!< Advertisement or SCAN_RSP RSSI + uint16_t periodicAdvInterval; //!< the interval of periodic advertising + uint8_t directAddressType; //!< public or random address type + uint8_t directAddress[B_ADDR_LEN]; //!< device address + uint8_t dataLen; //!< Length (in bytes) of the data field (evtData) + uint8_t *pEvtData; //!< Data field of advertisement or SCAN_RSP +} gapExtAdvDeviceInfoEvent_t; + +/** + * Type of device discovery (Scan) to perform. + */ +typedef struct +{ + uint8_t taskID; //!< Requesting App's Task ID, used to return results + uint8_t mode; //!< Discovery Mode: @ref GAP_DEVDISC_MODE_DEFINES + uint8_t activeScan; //!< TRUE for active scanning + uint8_t whiteList; //!< TRUE to only allow advertisements from devices in the white list. +} gapDevDiscReq_t; + +/** + * Type of device. + */ +typedef struct +{ + uint8_t eventType; //!< Indicates advertising event type used by the advertiser: @ref GAP_ADVERTISEMENT_REPORT_TYPE_DEFINES + uint8_t addrType; //!< Address Type: @ref GAP_ADDR_TYPE_DEFINES + uint8_t addr[B_ADDR_LEN]; //!< Device's Address +} gapDevRec_t; + +/** + * GAP_DEVICE_DISCOVERY_EVENT message format. This message is sent to the + * Application after a scan is performed. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_DEVICE_DISCOVERY_EVENT + uint8_t numDevs; //!< Number of devices found during scan + gapDevRec_t *pDevList; //!< array of device records +} gapDevDiscEvent_t; + +/** + * GAP_MAKE_DISCOVERABLE_DONE_EVENT message format. This message is sent to the + * app when the Advertise config is complete. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_MAKE_DISCOVERABLE_DONE_EVENT +} gapMakeDiscoverableRspEvent_t; + +/** + * GAP_END_DISCOVERABLE_DONE_EVENT message format. This message is sent to the + * app when the Advertising has stopped. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_END_DISCOVERABLE_DONE_EVENT +} gapEndDiscoverableRspEvent_t; + +/** + * GAP_PERIODIC_ADVERTISING_DONE_EVENT message format. This message is sent to the + * app when the Periodic Advertising config is complete. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_PERIODIC_ADVERTISING_DONE_EVENT +} gapMakePeriodicRspEvent_t; + +/** + * GAP_END_PERIODIC_ADV_DONE_EVENT message format. This message is sent to the + * app when the Periodic Advertising disable is complete. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_END_PERIODIC_ADV_DONE_EVENT +} gapEndPeriodicRspEvent_t; + +/** + * GAP_SYNC_ESTABLISHED_EVENT message format. This message is sent to the + * app when the Periodic Advertising Sync Establish is complete. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_SYNC_ESTABLISHED_EVENT + uint8_t status; //!< Periodic advertising sync status + uint16_t syncHandle; //!< Identifying the periodic advertising train + uint8_t advertisingSID; //!< Value of the Advertising SID subfield in the ADI field of the PDU + uint8_t devAddrType; //!< Device address type: @ref GAP_ADDR_TYPE_DEFINES + uint8_t devAddr[B_ADDR_LEN]; //!< Device address of sync + uint8_t advertisingPHY; //!< Advertiser PHY + uint16_t periodicInterval; //!< Periodic advertising interval + uint8_t clockAccuracy; //!< Clock Accuracy +} gapSyncEstablishedEvent_t; + +/** + * GAP_PERIODIC_ADV_DEVICE_INFO_EVENT message format. This message is sent to the + * app during Periodic Advertising Sync, when received a Periodic Advertising packet + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_PERIODIC_ADV_DEVICE_INFO_EVENT + uint16_t syncHandle; //!< Identifying the periodic advertising train + int8_t txPower; //!< Periodic advertising tx power,Units: dBm + int8_t rssi; //!< Periodic advertising rssi,Units: dBm + uint8_t unUsed; + uint8_t dataStatus; //!< Data complete + uint8_t dataLength; //!< Length (in bytes) of the data field (evtData) + uint8_t *pEvtData; //!< Data field of periodic advertising data +} gapPeriodicAdvDeviceInfoEvent_t; + +/** + * GAP_SYNC_LOST_EVENT message format. This message is sent to the + * app when the Periodic Advertising Sync timeout period. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_SYNC_LOST_EVENT + uint16_t syncHandle; //!< Identifying the periodic advertising train +} gapSyncLostEvent_t; + +/** + * GAP_SCAN_REQUEST_EVENT message format. This message is sent to the + * app when the advertiser receives a SCAN_REQ PDU or an AUX_SCAN_REQ PDU + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_SCAN_REQUEST_EVENT + uint8_t advHandle; //!< identifying the periodic advertising train + uint8_t scannerAddrType; //!< the type of the address + uint8_t scannerAddr[B_ADDR_LEN];//!< the address of scanner device +} gapScanReqReseiveEvent_t; + +/** + * GAP_ADV_DATA_UPDATE_DONE_EVENT message format. This message is sent to the + * app when Advertising Data Update is complete. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_ADV_DATA_UPDATE_DONE_EVENT + uint8_t adType; //!< TRUE if advertising data, FALSE if SCAN_RSP +} gapAdvDataUpdateEvent_t; + +/** + * GAP_LINK_ESTABLISHED_EVENT message format. This message is sent to the app + * when the link request is complete.
+ *
+ * For an Observer, this message is sent to complete the Establish Link Request.
+ * For a Peripheral, this message is sent to indicate that a link has been created. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_LINK_ESTABLISHED_EVENT + uint8_t devAddrType; //!< Device address type: @ref GAP_ADDR_TYPE_DEFINES + uint8_t devAddr[B_ADDR_LEN]; //!< Device address of link + uint16_t connectionHandle; //!< Connection Handle from controller used to ref the device + uint8_t connRole; //!< Connection formed as Master or Slave + uint16_t connInterval; //!< Connection Interval + uint16_t connLatency; //!< Connection Latency + uint16_t connTimeout; //!< Connection Timeout + uint8_t clockAccuracy; //!< Clock Accuracy +} gapEstLinkReqEvent_t; + +/** + * GAP_LINK_PARAM_UPDATE_EVENT message format. This message is sent to the app + * when the connection parameters update request is complete. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_LINK_PARAM_UPDATE_EVENT + uint8_t status; //!< bStatus_t + uint16_t connectionHandle; //!< Connection handle of the update + uint16_t connInterval; //!< Requested connection interval + uint16_t connLatency; //!< Requested connection latency + uint16_t connTimeout; //!< Requested connection timeout +} gapLinkUpdateEvent_t; + +/** + * GAP_LINK_TERMINATED_EVENT message format. This message is sent to the + * app when a link to a device is terminated. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_LINK_TERMINATED_EVENT + uint16_t connectionHandle; //!< connection Handle + uint8_t reason; //!< termination reason from LL + uint8_t connRole; +} gapTerminateLinkEvent_t; + +/** + * GAP_PHY_UPDATE_EVENT message format. This message is sent to the app(GAP_MSG_EVENT) + * when the PHY update request is complete. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_PHY_UPDATE_EVENT + uint8_t status; //!< bStatus_t + uint16_t connectionHandle; //!< Connection handle of the update + uint8_t connTxPHYS; //!< tx phy(GAP_PHY_VAL_TYPE) + uint8_t connRxPHYS; //!< rx phy(GAP_PHY_VAL_TYPE) +} gapPhyUpdateEvent_t; + +/** + * GAP_PASSKEY_NEEDED_EVENT message format. This message is sent to the + * app when a Passkey is needed from the app's user interface. + */ +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_PASSKEY_NEEDED_EVENT + uint8_t deviceAddr[B_ADDR_LEN]; //!< address of device to pair with, and could be either public or random. + uint16_t connectionHandle; //!< Connection handle + uint8_t uiInputs; //!< Pairing User Interface Inputs - Ask user to input passcode + uint8_t uiOutputs; //!< Pairing User Interface Outputs - Display passcode +} gapPasskeyNeededEvent_t; + +/** + * Passcode Callback Function + */ +typedef void (*pfnPasscodeCB_t)( uint8_t *deviceAddr, //!< address of device to pair with, and could be either public or random. + uint16_t connectionHandle, //!< Connection handle + uint8_t uiInputs, //!< Pairing User Interface Inputs - Ask user to input passcode + uint8_t uiOutputs //!< Pairing User Interface Outputs - Display passcode + ); + +/** + * Pairing State Callback Function + */ +typedef void (*pfnPairStateCB_t)( uint16_t connectionHandle, //!< Connection handle + uint8_t state, //!< Pairing state @ref GAPBOND_PAIRING_STATE_DEFINES + uint8_t status //!< Pairing status + ); + +typedef struct +{ + tmos_event_hdr_t hdr; //!< GAP_MSG_EVENT and status + uint8_t opcode; //!< GAP_O0B_NEEDED_EVENT + uint8_t deviceAddr[B_ADDR_LEN]; //!< address of device to pair with, and could be either public or random. + uint16_t connectionHandle; //!< Connection handle + uint8_t r_local[16]; + uint8_t c_local[16]; +} gapOobNeededEvent_t; + +/** + * OOB Callback Function + */ +typedef void (*pfnOobCB_t)( uint8_t *deviceAddr, //!< address of device to pair with, and could be either public or random. + uint16_t connectionHandle, //!< Connection handle + uint8_t* r_local, //!< local rand + uint8_t *c_local //!< local confirm + ); + +/** + * Callback Registration Structure + */ +typedef struct +{ + pfnPasscodeCB_t passcodeCB; //!< Passcode callback + pfnPairStateCB_t pairStateCB; //!< Pairing state callback + pfnOobCB_t oobCB; //!< oob callback +} gapBondCBs_t; + +typedef int (*pfnEcc_key_t)( uint8_t *pub, uint8_t *priv); + +typedef int (*pfnEcc_dhkey_t)( uint8_t *peer_pub_key_x, uint8_t *peer_pub_key_y, + uint8_t *our_priv_key, uint8_t *out_dhkey ); + +typedef int (*pfnEcc_alg_f4_t)( uint8_t *u, uint8_t *v, uint8_t *x, uint8_t z, + uint8_t *out_enc_data ); + +typedef int (*pfnEcc_alg_g2_t)( uint8_t *u, uint8_t *v, uint8_t *x, uint8_t *y, + uint32_t *passkey ); + +typedef int (*pfnEcc_alg_f5_t)( uint8_t *w, uint8_t *n1, uint8_t *n2, + uint8_t a1t, uint8_t *a1, uint8_t a2t, uint8_t *a2, uint8_t *mackey, uint8_t *ltk ); + +typedef int (*pfnEcc_alg_f6_t)( uint8_t *w, uint8_t *n1, uint8_t *n2, uint8_t *r, + uint8_t *iocap, uint8_t a1t, uint8_t *a1, uint8_t a2t, uint8_t *a2, uint8_t *check ); + +/** + * Callback Registration Structure + */ +typedef struct +{ + pfnEcc_key_t gen_key_pair; + pfnEcc_dhkey_t gen_dhkey; + pfnEcc_alg_f4_t alg_f4; //!< LE Secure Connections confirm value generation function f4 + pfnEcc_alg_g2_t alg_g2; //!< LE Secure Connections numeric comparison value generation function g2 + pfnEcc_alg_f5_t alg_f5; //!< LE Secure Connect ions key generation function f5 + pfnEcc_alg_f6_t alg_f6; //!< LE Secure Connections check value generation function f6 +} gapEccCBs_t; + +/** + * gapRole_States_t defined + */ +typedef unsigned long gapRole_States_t; + +// gapRole_States_t @ 4b'[3-0]-advertising states +#define GAPROLE_STATE_ADV_MASK (0xF) //!< advertising states mask +#define GAPROLE_STATE_ADV_SHIFT (0x0) //!< advertising states shift +#define GAPROLE_INIT 0 //!< Waiting to be started +#define GAPROLE_STARTED 1 //!< Started but not advertising +#define GAPROLE_ADVERTISING 2 //!< Currently Advertising +#define GAPROLE_WAITING 3 //!< Device is started but not advertising, is in waiting period before advertising again +#define GAPROLE_CONNECTED 4 //!< In a connection +#define GAPROLE_CONNECTED_ADV 5 //!< In a connection + advertising +#define GAPROLE_ERROR 6 //!< Error occurred - invalid state + +// gapRole_States_t @ 4b'[7-4]-Periodic advertising states +// Periodic advertising Enable,only effective when GAP_ADTYPE_EXT_NONCONN_NONSCAN_UNDIRECT advertising event enable +#define GAPROLE_STATE_PERIODIC_MASK (0xF0) //!< Periodic advertising states mask +#define GAPROLE_STATE_PERIODIC_SHIFT (4) //!< Periodic advertising states shift +#define GAPROLE_PERIODIC_INVALID (0<<4) //!< Periodic advertising Waiting to be started +#define GAPROLE_PERIODIC_ENABLE (1<<4) //!< Periodic advertising Enable +#define GAPROLE_PERIODIC_WAIT (2<<4) //!< Periodic advertising is started but disable +#define GAPROLE_PERIODIC_ERROR (3<<4) //!< Periodic advertising error occurred + +// gapRole_States_t @ 16b'[23-8]- Reserved for future use + +// gapRole_States_t @ 8b'[31-24] - indicates which fields change +#define GAPROLE_PERIODIC_STATE_VALID (1<<24) //!< indicates periodic advertising states change + +/** + * gapRole Event Structure + */ +typedef union +{ + gapEventHdr_t gap; //!< GAP_MSG_EVENT and status. + gapDeviceInitDoneEvent_t initDone; //!< GAP initialization done. + gapDeviceInfoEvent_t deviceInfo; //!< Discovery device information event structure. + gapDirectDeviceInfoEvent_t deviceDirectInfo; //!< Discovery direct device information event structure. + gapAdvDataUpdateEvent_t dataUpdate; //!< Advertising Data Update is complete. + gapPeriodicAdvDeviceInfoEvent_t devicePeriodicInfo; //!< Discovery periodic device information event structure. + gapExtAdvDeviceInfoEvent_t deviceExtAdvInfo; //!< Discovery extend advertising device information event structure. + gapDevDiscEvent_t discCmpl; //!< Discovery complete event structure. + gapSyncEstablishedEvent_t syncEstEvt; //!< sync established event structure. + gapSyncLostEvent_t syncLostEvt; //!< sync lost event structure. + gapScanReqReseiveEvent_t scanReqEvt; //!< Scan_Request_Received event structure. + + gapEstLinkReqEvent_t linkCmpl; //!< Link complete event structure. + gapLinkUpdateEvent_t linkUpdate; //!< Link update event structure. + gapTerminateLinkEvent_t linkTerminate; //!< Link terminated event structure. + gapPhyUpdateEvent_t linkPhyUpdate; //!< Link phy update event structure. +} gapRoleEvent_t; + +/** + * Type of device. + */ +typedef struct +{ + uint8_t eventType; //!< Indicates advertising event type used by the advertiser: @ref GAP_ADVERTISEMENT_REPORT_TYPE_DEFINES + uint8_t addrType; //!< Scan Address Type:0x00-Public Device Address or Public Identity Address 0x01-Random Device Address or Random (static) Identity Address + uint8_t addr[B_ADDR_LEN]; //!< Device's Address + int8_t rssi; +} gapScanRec_t; + +/** + * Type of GAPRole_CreateSync command parameters. + */ +typedef struct +{ + uint8_t options; + /* + bit0: used to determine whether the Periodic Advertiser List is used + 0: Use the Advertising_SID, Advertisier_Address_Type, and Advertiser_Address parameters to determine which advertiser to listen to. + 1: Use the Periodic Advertiser List to determine which advertiser to listen to. + bit1: whether GAP_PERIODIC_ADV_DEVICE_INFO_EVENT events for this periodic advertising train are initially enabled or disabled. + 0: Reporting initially enabled + 1: Reporting initially disabled + bit2: + 0: Duplicate filtering initially disabled + 1: Duplicate filtering initially enabled */ + uint8_t advertising_SID; //!< if used, specifies the value that must match the Advertising SID + uint8_t addrType; //!< Scan Address Type: @ref GAP_ADDR_TYPE_DEFINES + uint8_t addr[B_ADDR_LEN]; //!< Device's Address + uint16_t skip; //!< the maximum number of consecutive periodic advertising events that the receiver may skip after + //!< successfully receiving a periodic advertising packet.Range: 0x0000 to 0x01F3 + uint16_t syncTimeout; //!< the maximum permitted time between successful receives. If this time is exceeded, synchronization is lost. + //!< Time = N*10 ms.Range: 0x000A to 0x4000 + uint8_t syncCTEType; //!< specifies whether to only synchronize to periodic advertising with certain types of Constant Tone Extension + //!< (a value of 0 indicates that the presence or absence of a Constant Tone Extension is irrelevant). +} gapCreateSync_t; + +/** + * Type of GAPRole_SetPathLossReporting command parameters. + */ +typedef struct +{ + uint16_t connHandle; //!< Used to identify the Connection handle + int8_t highThreshold; //!< High threshold for the path loss.Units: dB + int8_t highHysteresis; //!< Hysteresis value for the high threshold.Units: dB + int8_t lowThreshold; //!< High threshold for the path loss.Units: dB + int8_t lowHysteresis; //!< Hysteresis value for the high threshold.Units: dB + uint16_t minTimeSpent; //!< Minimum time in number of connection events to be observed + //!< once the path crosses the threshold before an event is generated. + uint8_t enable; //!< 0x00:Reporting disabled 0x01:Reporting enabled +} gapRoleSetPathLossReporting_t; + +typedef struct +{ + uint16_t connHandle; //!< Used to identify the Connection handle + int8_t lowRxThreshold; //!< High threshold for the peer power levels.Units: dB + int8_t highRxThreshold; //!< High threshold for the peer power levels.Units: dB + int8_t minTxPower; //!< Minimum transmit power level.Units: dB + int8_t maxTxPower; //!< Maximum transmit power level.Units: dB +} gapRolePowerlevelManagement_t; + +/** + * Callback when the device has been started. Callback event to + * the Notify of a state change. + */ +typedef void (*gapRolesBroadcasterStateNotify_t)( gapRole_States_t newState ); + +typedef void (*gapRolesScanReqRecv_t)( gapScanRec_t * pEvent ); + +typedef struct +{ + gapRolesBroadcasterStateNotify_t pfnStateChange; //!< Whenever the device changes state + gapRolesScanReqRecv_t pfnScanRecv; +} gapRolesBroadcasterCBs_t; + +/** + * Observer Event Callback Function + */ +typedef void (*pfnGapObserverRoleEventCB_t)( gapRoleEvent_t *pEvent //!< Pointer to event structure. + ); + +/** + * Observer Callback Structure + */ +typedef struct +{ + pfnGapObserverRoleEventCB_t eventCB; //!< Event callback. +} gapRoleObserverCB_t; + +/** + * Callback when the device has read an new RSSI value during a connection. + */ +typedef void (*gapRolesRssiRead_t)( uint16_t connHandle, int8_t newRSSI ); + +/** + * Callback when the device has been started. Callback event to + * the Notify of a state change. + */ +typedef void (*gapRolesStateNotify_t)( gapRole_States_t newState, gapRoleEvent_t * pEvent ); + +/** + * Callback when the connection parameteres are updated. + */ +typedef void (*gapRolesParamUpdateCB_t)( uint16_t connHandle, uint16_t connInterval, + uint16_t connSlaveLatency, uint16_t connTimeout ); + +/** + * Callback structure - must be setup by the application and used when gapRoles_StartDevice() is called. + */ +typedef struct +{ + gapRolesStateNotify_t pfnStateChange; //!< Whenever the device changes state + gapRolesRssiRead_t pfnRssiRead; //!< When a valid RSSI is read from controller + gapRolesParamUpdateCB_t pfnParamUpdate; //!< When the connection parameteres are updated +} gapRolesCBs_t; + +/** + * Central Event Callback Function + */ +typedef void (*pfnGapCentralRoleEventCB_t)( gapRoleEvent_t *pEvent ); //!< Pointer to event structure. + +/** + * HCI Data Length Change Event Callback Function + */ +typedef void (*pfnHciDataLenChangeEvCB_t)( uint16_t connHandle, uint16_t maxTxOctets, + uint16_t maxRxOctets ); + +/** + * Central Callback Structure + */ +typedef struct +{ + gapRolesRssiRead_t rssiCB; //!< RSSI callback. + pfnGapCentralRoleEventCB_t eventCB; //!< Event callback. + pfnHciDataLenChangeEvCB_t ChangCB; //!< Length Change Event Callback . +} gapCentralRoleCB_t; // gapCentralRoleCB_t + +/* RF-PHY define */ + +/* + * RF_ROLE_STATUS_TYPE pfnRFStatusCB_t state defined + */ +// TX_MODE call RF_Tx +#define TX_MODE_TX_FINISH 0x01 //!< basic or auto tx mode sends data successfully + //!< if it is in basic mode,it will enter idle state; + //!< if it is in auto mode,it will wait for receiving +#define TX_MODE_TX_FAIL 0x11 //!< basic or auto tx mode fail to send data and enter idle state +#define TX_MODE_TX_TIMEOUT TX_MODE_TX_FAIL //!< time of data transmission +#define TX_MODE_RX_DATA 0x02 //!< auto tx mode receive data(ack) and enter idle state +#define TX_MODE_RX_TIMEOUT 0x12 //!< auto tx mode receive timeout and enter idle state +#define TX_MODE_HOP_SHUT 0x22 + +// RX_MODE call RF_Rx +#define RX_MODE_RX_DATA 0x03 //!< basic or auto rx mode receive data + //!< if it is in basic mode,it will enter idle state; + //!< if it is in auto mode,it will judge whether the type matches; + //!< if it matches,it will send data(ack),otherwise(rsr=2), it will restart receiving +#define RX_MODE_TX_FINISH 0x04 //!< auto rx mode sends data(ack) successfully and enters idle state +#define RX_MODE_TX_FAIL 0x14 //!< auto rx mode fail to send data and enter idle state +#define RX_MODE_TX_TIMEOUT RX_MODE_TX_FAIL //!< time of data transmission +#define RX_MODE_HOP_SHUT 0x24 + +// LLE_MODE_TYPE +#define LLE_MODE_BASIC (0) //!< basic mode, enter idle state after sending or receive +#define LLE_MODE_AUTO (1) //!< auto mode, auto swtich to the receiving status after sending and the sending status after receiving + +// LLE_WHITENING_TYPE +#define LLE_WHITENING_ON (0<<1) +#define LLE_WHITENING_OFF (1<<1) + +// LLE_PHY_TYPE +#define LLE_MODE_PHY_MODE_MASK (0x30) +#define LLE_MODE_PHY_1M (0<<4) +#define LLE_MODE_PHY_2M (1<<4) +#define LLE_MODE_PHY_CODED_S8 (2<<4) +#define LLE_MODE_PHY_CODED_S2 (3<<4) + +#define LLE_MODE_EX_CHANNEL (1<<6) + +#define LLE_MODE_NON_RSSI (1<<7) + +/** + * RFRole Event Callback Function + */ +typedef void (*pfnRFStatusCB_t)( uint8_t sta, uint8_t rsr, uint8_t *rxBuf ); +// sta - current status@ref RF_ROLE_STATUS_TYPE +// rsr - receive status: bit0- crc check result,bit1- type matching result +// rxBuf - receive data buffer + +typedef struct tag_rf_config +{ + uint8_t LLEMode; //!< BIT0 0=basic, 1=auto def@LLE_MODE_TYPE + //!< BIT1 0=whitening on, 1=whitening off def@LLE_WHITENING_TYPE + //!< BIT4-5 00-1M 01-2M 10-coded(S8) 11-coded(S2) def@LLE_PHY_TYPE + //!< BIT6 0=data channel(0-39) + //!< 1=rf frequency (2400000kHz-2483500kHz) + //!< BIT7 0=the first byte of the receive buffer is rssi + //!< 1=the first byte of the receive buffer is package type + uint8_t Channel; //!< rf channel(0-39) + uint32_t Frequency; //!< rf frequency (2400000kHz-2483500kHz) + uint32_t accessAddress; //!< access address,32bit PHY address + uint32_t CRCInit; //!< crc initial value + pfnRFStatusCB_t rfStatusCB; //!< status call back + uint32_t ChannelMap; //!< indicating Used and Unused data channels.Every channel is represented with a + //!< bit positioned as per the data channel index,The LSB represents data channel index 0 + uint8_t Resv; + uint8_t HeartPeriod; //!< The heart package interval shall be an integer multiple of 100ms + uint8_t HopPeriod; //!< hop period( T=32n*RTC clock ),default is 8 + uint8_t HopIndex; //!< indicate the hopIncrement used in the data channel selection algorithm,default is 17 + uint8_t RxMaxlen; //!< Maximum data length received in rf-mode(default 251) + uint8_t TxMaxlen; //!< Maximum data length transmit in rf-mode(default 251) +} rfConfig_t; + +/* end define@RF-PHY */ + +/******************************************************************************* + * UUID defined + */ +/** + * GATT Services + */ +extern const uint8_t gapServiceUUID[]; +extern const uint8_t gattServiceUUID[]; + +/** + * GATT Attribute Types + */ +extern const uint8_t primaryServiceUUID[]; +extern const uint8_t secondaryServiceUUID[]; +extern const uint8_t includeUUID[]; +extern const uint8_t characterUUID[]; + +/** + * GATT Characteristic Descriptors + */ +extern const uint8_t charExtPropsUUID[]; +extern const uint8_t charUserDescUUID[]; +extern const uint8_t clientCharCfgUUID[]; +extern const uint8_t servCharCfgUUID[]; +extern const uint8_t charFormatUUID[]; +extern const uint8_t charAggFormatUUID[]; +extern const uint8_t validRangeUUID[]; +extern const uint8_t extReportRefUUID[]; +extern const uint8_t reportRefUUID[]; + +/** + * GATT Characteristic Types + */ +extern const uint8_t deviceNameUUID[]; +extern const uint8_t appearanceUUID[]; +extern const uint8_t periPrivacyFlagUUID[]; +extern const uint8_t reconnectAddrUUID[]; +extern const uint8_t periConnParamUUID[]; +extern const uint8_t serviceChangedUUID[]; +extern const uint8_t centAddrResUUID[]; + +/******************************************************************************* + * PUBLIC FUNCTIONS + */ +extern uint32_t tmos_rand( void ); // pseudo-random number +extern BOOL tmos_memcmp( const void *src1, const void *src2, uint32_t len ); // TRUE - same, FALSE - different +extern BOOL tmos_isbufset( uint8_t *buf, uint8_t val, uint32_t len ); // TRUE if all "val",FALSE otherwise +extern uint32_t tmos_strlen( char *pString ); +extern void tmos_memset( void * pDst, uint8_t Value, uint32_t len ); +extern void tmos_memcpy( void *dst, const void *src, uint32_t len ); // Generic memory copy. + +/** + * @brief start a event immediately + * + * @param taskID - task ID of event + * @param event - event value + * + * @return 0 - SUCCESS. + */ +extern bStatus_t tmos_set_event( tmosTaskID taskID, tmosEvents event ); + +/** + * @brief clear a event already timeout, cannot be used in it own event function. + * + * @param taskID - task ID of event + * @param event - event value + * + * @return 0 - SUCCESS. + */ +extern bStatus_t tmos_clear_event( tmosTaskID taskID, tmosEvents event ); + +/** + * @brief start a event after period of time + * + * @param taskID - task ID to set event for + * @param event - event to be notified with + * @param time - timeout value + * + * @return TRUE,FALSE. + */ +extern BOOL tmos_start_task( tmosTaskID taskID, tmosEvents event, tmosTimer time ); + +/** + * @brief This function is called to start a timer to expire in n system clock time. + * When the timer expires, the calling task will get the specified event + * and the timer will be reloaded with the timeout value. + * + * @param taskID - task ID to set timer for + * @param event - event to be notified with + * @param time - timeout value + * + * @return SUCCESS, or NO_TIMER_AVAIL. + */ +extern bStatus_t tmos_start_reload_task( tmosTaskID taskID, tmosEvents event, tmosTimer time ); + +/** + * @brief stop a event + * + * @param taskID - task ID of event + * @param event - event value + * + * @param None. + * + * @return SUCCESS. + */ +extern bStatus_t tmos_stop_task( tmosTaskID taskID, tmosEvents event ); + +/** + * @brief get last period of time for this event + * + * @param taskID - task ID of event + * @param event - event value + * + * @return the timer's tick count if found, zero otherwise. + */ +extern tmosTimer tmos_get_task_timer( tmosTaskID taskID, tmosEvents event ); + +/** + * @brief send msg to a task,callback events&SYS_EVENT_MSG + * + * @param taskID - task ID of task need to send msg + * @param *msg_ptr - point of msg + * + * @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER + */ +extern bStatus_t tmos_msg_send( tmosTaskID taskID, uint8_t *msg_ptr ); + +/** + * @brief delete a msg + * + * @param *msg_ptr - point of msg + * + * @return SUCCESS. + */ +extern bStatus_t tmos_msg_deallocate( uint8_t *msg_ptr ); + +/** + * @brief receive a msg + * + * @param taskID - task ID of task need to receive msg + * + * @return *uint8_t - message information or NULL if no message + */ +extern uint8_t *tmos_msg_receive( tmosTaskID taskID ); + +/** + * @brief allocate buffer for msg when need to send msg + * + * @param len - length of msg + * + * @return pointer to allocated buffer or NULL if allocation failed. + */ +extern uint8_t *tmos_msg_allocate( uint16_t len ); + +/** + * @brief read a data item to NV. + * + * @param id - Valid NV item Id. + * @param len - Length of data to read. + * @param *pBuf - Data to read. + * + * @return SUCCESS if successful, NV_OPER_FAILED if failed. + */ +extern bStatus_t tmos_snv_read( tmosSnvId_t id, tmosSnvLen_t len, void *pBuf ); + +/** + * @brief tmos system timer initialization + * + * @note must initialization before call tmos task + * + * @param fnGetClock - 0:system clock select RTC timer + * valid:system clock select extend input + * + * @return SUCCESS if successful, FAILURE if failed. + */ +extern bStatus_t TMOS_TimerInit( pfnGetSysClock fnGetClock ); + +/** + * @brief interrupt handler. + * + * @param None + * + * @return None + */ +extern void TMOS_TimerIRQHandler( void ); + +/** + * @brief Process system + * + * @param None. + * + * @return None. + */ +extern void TMOS_SystemProcess( void ); + +/** + * @brief Get current system clock + * + * @param None. + * + * @return current system clock (in 0.625ms) + */ +extern uint32_t TMOS_GetSystemClock( void ); + +/** + * @brief register process event callback function + * + * @param eventCb-events callback function + * + * @return 0xFF - error,others-task id + */ +extern tmosTaskID TMOS_ProcessEventRegister( pTaskEventHandlerFn eventCb ); + +/** + * @brief Add a device address into white list ( support SNVNum MAX ) + * + * @param addrType - Type of device address + * @param devAddr - first address of device address + * + * @return Command Status. + */ +extern bStatus_t LL_AddWhiteListDevice( uint8_t addrType, uint8_t *devAddr ); + +/** + * @brief Remove a device address from white list + * + * @param addrType - Type of device address + * @param devAddr - first address of device address + * + * @return Command Status. + */ +extern bStatus_t LL_RemoveWhiteListDevice( uint8_t addrType, uint8_t *devAddr ); + +/** + * @brief Clear white list + * + * @param None + * + * @return Command Status. + */ +extern bStatus_t LL_ClearWhiteList( void ); + +/** + * @brief Encrypt data + * + * @param key - key + * @param plaintextData - original data + * @param encryptData - encrypted data + * + * @return Command Status. + */ +extern bStatus_t LL_Encrypt( uint8_t *key, uint8_t *plaintextData, uint8_t *encryptData ); + +/** + * @brief Decrypt data + * + * @param key - key + * @param plaintextData - original data + * @param decryptData - decrypted data + * + * @return Command Status. + */ +extern bStatus_t LL_Decrypt( uint8_t *key, uint8_t *plaintextData, uint8_t *decryptData ); + +/** + * @brief get number of unAck packet in current connect buffer + * + * @param handle - connect handle + * + * @return 0xFFFFFFFF-handle error,number of packets not receiving ack + */ +extern uint32_t LL_GetNumberOfUnAckPacket( uint16_t handle ); + +/** + * @brief Register a callback function will be called after each connect event. + * Only effect in single connection + * + * @param connEventCB - callback function + * + * @return None. + */ +extern void LL_ConnectEventRegister( pfnEventCB connEventCB ); + +/** + * @brief Register a callback function will be called after each advertise event. + * + * @param advEventCB - callback function + * + * @return None. + */ +extern void LL_AdvertiseEventRegister( pfnEventCB advEventCB ); + +/** + * @brief set tx power level + * + * @param power - tx power level + * + * @return Command Status. + */ +extern bStatus_t LL_SetTxPowerLevel( uint8_t power ); + +/** + * @brief read rssi + * + * @param None. + * + * @return the value of rssi. + */ +extern int8_t BLE_ReadRssi( void ); + +/** + * @brief read cfo + * + * @param None. + * + * @return the value of cfo. + */ +extern int16_t BLE_ReadCfo( void ); + +/** + * @brief pa control init + * + * @note Can't be called until role Init + * + * @param paControl - pa control parameters(global variable) + * + * @return Command Status. + */ +extern void BLE_PAControlInit( blePaControlConfig_t *paControl ); + +/** + * @brief ble register reset and rf calibration + * + * @param None + * + * @return None + */ +extern void BLE_RegInit( void ); + +/** + * @brief Init BLE lib. RTC will be occupied at the same time. + * + * @param pCfg - config of BLE lib + * + * @return 0-success. error defined @ ERR_LIB_INIT + */ +extern bStatus_t BLE_LibInit( bleConfig_t* pCfg ); + +/** + * @brief interrupt handler. + * + * @param None + * + * @return None + */ +extern void BB_IRQLibHandler( void ); + +/** + * @brief interrupt handler. + * + * @param None + * + * @return None + */ +extern void LLE_IRQLibHandler( void ); + +/** + * @brief generate a valid access address + * + * @param None. + * + * @return access address + * the Access Address meets the following requirements: + * It shall have no more than six consecutive zeros or ones. + * It shall not be t he advertising channel packets�� Access Address. + * It shall not be a sequence that differ s from the advertising channel packets' Access Address by only one bit. + * It shall not have all four octets equal. + * It shall have no more than 24 transitions. + * It shall have a minimum of two transitions in the most significant six bits. + */ +extern uint32_t BLE_AccessAddressGenerate( void ); + +/* + * linkDB_Register - Register with this function to receive a callback when + * status changes on a connection. + */ +extern uint8_t linkDB_Register( pfnLinkDBCB_t pFunc ); + +/* + * linkDB_State - Check to see if a physical link is in a specific state. + * + * returns TRUE is the link is in state. FALSE, otherwise. + */ +extern uint8_t linkDB_State( uint16_t connectionHandle, uint8_t state ); + +/* + * linkDB_PerformFunc - Perform a function of each connection in the link database. + */ +extern void linkDB_PerformFunc( pfnPerformFuncCB_t cb ); +/* + * linkDB_Up - Check to see if a physical link is up (connected). + * Use like: uint8_t linkDB_Up( uint16_t connectionHandle ); + * connectionHandle - controller link connection handle. + * returns TRUE if the link is up. FALSE, otherwise. + */ +#define linkDB_Up( connectionHandle ) linkDB_State( (connectionHandle), LINK_CONNECTED ) + +/** + * @brief This function is used to get the MTU size of a connection. + * + * @param connHandle - connection handle. + * + * @return connection MTU size.
+ */ +extern uint16_t ATT_GetMTU( uint16_t connHandle ); + +/** + * @brief Send Handle Value Confirmation. + * + * @param connHandle - connection to use + * + * @return SUCCESS: Confirmation was sent successfully.
+ * INVALIDPARAMETER: Invalid confirmation field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * bleMemAllocError: Memory allocation error occurred.
+ */ +extern bStatus_t ATT_HandleValueCfm( uint16_t connHandle ); + +/* + * Compare two UUIDs. The UUIDs are converted if necessary. + */ +extern uint8_t ATT_CompareUUID( const uint8_t *pUUID1, uint16_t len1, const uint8_t *pUUID2, uint16_t len2 ); + +/** + * @brief Initialize the Generic Attribute Profile Client. + * + * @return SUCCESS: Client initialized successfully.
+ * bleMemAllocError: Memory allocation error occurred.
+ */ +extern bStatus_t GATT_InitClient( void ); + +/** + * @brief Register to receive incoming ATT Indications or Notifications + * of attribute values. + * + * @param taskId ?task to forward indications or notifications to + * + * @return void + */ +extern void GATT_RegisterForInd( uint8_t taskId ); + +/** + * @brief Find the attribute record for a given handle + * + * @param handle - handle to look for + * @param pHandle - handle of owner of attribute (to be returned) + * + * @return Pointer to attribute record. NULL, otherwise. + */ +extern gattAttribute_t *GATT_FindHandle( uint16_t handle, uint16_t *pHandle ); + +/** + * @brief This sub-procedure is used when a server is configured to + * indicate a characteristic value to a client and expects an + * attribute protocol layer acknowledgement that the indication + * was successfully received. + * + * The ATT Handle Value Indication is used in this sub-procedure. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive an tmos GATT_MSG_EVENT message. + * The type of the message will be ATT_HANDLE_VALUE_CFM. + * + * @note This sub-procedure is complete when ATT_HANDLE_VALUE_CFM + * (with SUCCESS or bleTimeoutstatus) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pInd - pointer to indication to be sent + * @param authenticated - whether an authenticated link is required + * @param taskId - task to be notified of response + * + * @return SUCCESS: Indication was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A confirmation is pending with this client.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_Indication( uint16_t connHandle, attHandleValueInd_t *pInd, uint8_t authenticated, uint8_t taskId ); +/** + * @brief This sub-procedure is used when a server is configured to + * notify a characteristic value to a client without expecting + * any attribute protocol layer acknowledgement that the + * notification was successfully received. + * + * The ATT Handle Value Notification is used in this sub-procedure. + * + * @note A notification may be sent at any time and does not invoke a confirmation. + * No confirmation will be sent to the calling application task for + * this sub-procedure. + * + * @param connHandle - connection to use + * @param pNoti - pointer to notification to be sent + * @param authenticated - whether an authenticated link is required + * + * @return SUCCESS: Notification was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_Notification( uint16_t connHandle, attHandleValueNoti_t *pNoti, uint8_t authenticated ); + +/** + * @brief This sub-procedure is used by the client to set the ATT_MTU + * to the maximum possible value that can be supported by both + * devices when the client supports a value greater than the + * default ATT_MTU for the Attribute Protocol. This sub-procedure + * shall only be initiated once during a connection. + * + * The ATT Exchange MTU Request is used by this sub-procedure. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive an tmos GATT_MSG_EVENT message. + * The type of the message will be either ATT_EXCHANGE_MTU_RSP or + * ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_EXCHANGE_MTU_RSP + * (with SUCCESS or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_ExchangeMTU( uint16_t connHandle, attExchangeMTUReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used by a client to discover all + * the primary services on a server. + * + * The ATT Read By Group Type Request is used with the Attribute + * Type parameter set to the UUID for "Primary Service". The + * Starting Handle is set to 0x0001 and the Ending Handle is + * set to 0xFFFF. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_READ_BY_GRP_TYPE_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_BY_GRP_TYPE_RSP + * (with bleProcedureComplete or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_DiscAllPrimaryServices( uint16_t connHandle, uint8_t taskId ); + +/** + * @brief This sub-procedure is used by a client to discover a specific + * primary service on a server when only the Service UUID is + * known. The primary specific service may exist multiple times + * on a server. The primary service being discovered is identified + * by the service UUID. + * + * The ATT Find By Type Value Request is used with the Attribute + * Type parameter set to the UUID for "Primary Service" and the + * Attribute Value set to the 16-bit Bluetooth UUID or 128-bit + * UUID for the specific primary service. The Starting Handle shall + * be set to 0x0001 and the Ending Handle shall be set to 0xFFFF. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_FIND_BY_TYPE_VALUE_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_FIND_BY_TYPE_VALUE_RSP + * (with bleProcedureComplete or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pUUID - pointer to service UUID to look for + * @param len - length of value + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_DiscPrimaryServiceByUUID( uint16_t connHandle, uint8_t *pUUID, uint8_t len, uint8_t taskId ); + +/** + * @brief This sub-procedure is used by a client to find include + * service declarations within a service definition on a + * server. The service specified is identified by the service + * handle range. + * + * The ATT Read By Type Request is used with the Attribute + * Type parameter set to the UUID for "Included Service". The + * Starting Handle is set to starting handle of the specified + * service and the Ending Handle is set to the ending handle + * of the specified service. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_READ_BY_TYPE_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_BY_TYPE_RSP + * (with bleProcedureCompleteor bleTimeout status)or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param startHandle - starting handle + * @param endHandle - end handle + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_FindIncludedServices( uint16_t connHandle, uint16_t startHandle, uint16_t endHandle, uint8_t taskId ); + +/** + * @brief This sub-procedure is used by a client to find all the + * characteristic declarations within a service definition on + * a server when only the service handle range is known. The + * service specified is identified by the service handle range. + * + * The ATT Read By Type Request is used with the Attribute Type + * parameter set to the UUID for "Characteristic". The Starting + * Handle is set to starting handle of the specified service and + * the Ending Handle is set to the ending handle of the specified + * service. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_READ_BY_TYPE_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_BY_TYPE_RSP + * (with bleProcedureComplete or bleTimeout status)or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param startHandle - starting handle + * @param endHandle - end handle + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_DiscAllChars( uint16_t connHandle, uint16_t startHandle, uint16_t endHandle, uint8_t taskId ); + +/** + * @brief This sub-procedure is used by a client to discover service + * characteristics on a server when only the service handle + * ranges are known and the characteristic UUID is known. + * The specific service may exist multiple times on a server. + * The characteristic being discovered is identified by the + * characteristic UUID. + * + * The ATT Read By Type Request is used with the Attribute Type + * is set to the UUID for "Characteristic" and the Starting + * Handle and Ending Handle parameters is set to the service + * handle range. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_READ_BY_TYPE_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_BY_TYPE_RSP + * (with bleProcedureComplete or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_DiscCharsByUUID( uint16_t connHandle, attReadByTypeReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used by a client to find all the + * characteristic descriptors Attribute Handles and Attribute + * Types within a characteristic definition when only the + * characteristic handle range is known. The characteristic + * specified is identified by the characteristic handle range. + * + * The ATT Find Information Request is used with the Starting + * Handle set to starting handle of the specified characteristic + * and the Ending Handle set to the ending handle of the specified + * characteristic. The UUID Filter parameter is NULL (zero length). + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_FIND_INFO_RSP or + * ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_FIND_INFO_RSP + * (with bleProcedureComplete or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param startHandle - starting handle + * @param endHandle - end handle + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_DiscAllCharDescs( uint16_t connHandle, uint16_t startHandle, uint16_t endHandle, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to read a Characteristic Value + * from a server when the client knows the Characteristic Value + * Handle. The ATT Read Request is used with the Attribute Handle + * parameter set to the Characteristic Value Handle. The Read + * Response returns the Characteristic Value in the Attribute + * Value parameter. + * + * The Read Response only contains a Characteristic Value that + * is less than or equal to (ATT_MTU ?1) octets in length. If + * the Characteristic Value is greater than (ATT_MTU - 1) octets + * in length, the Read Long Characteristic Value procedure may + * be used if the rest of the Characteristic Value is required. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive an tmos GATT_MSG_EVENT message. + * The type of the message will be either ATT_READ_RSP or + * ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_RSP + * (with SUCCESS or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_ReadCharValue( uint16_t connHandle, attReadReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to read a Characteristic Value + * from a server when the client only knows the characteristic + * UUID and does not know the handle of the characteristic. + * + * The ATT Read By Type Request is used to perform the sub-procedure. + * The Attribute Type is set to the known characteristic UUID and + * the Starting Handle and Ending Handle parameters shall be set + * to the range over which this read is to be performed. This is + * typically the handle range for the service in which the + * characteristic belongs. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive an tmos GATT_MSG_EVENT messages. + * The type of the message will be either ATT_READ_BY_TYPE_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_BY_TYPE_RSP + * (with SUCCESS or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_ReadUsingCharUUID( uint16_t connHandle, attReadByTypeReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to read a Characteristic Value from + * a server when the client knows the Characteristic Value Handle + * and the length of the Characteristic Value is longer than can + * be sent in a single Read Response Attribute Protocol message. + * + * The ATT Read Blob Request is used in this sub-procedure. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_READ_BLOB_RSP or + * ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_BLOB_RSP + * (with bleProcedureComplete or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_ReadLongCharValue( uint16_t connHandle, attReadBlobReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to read multiple Characteristic Values + * from a server when the client knows the Characteristic Value + * Handles. The Attribute Protocol Read Multiple Requests is used + * with the Set Of Handles parameter set to the Characteristic Value + * Handles. The Read Multiple Response returns the Characteristic + * Values in the Set Of Values parameter. + * + * The ATT Read Multiple Request is used in this sub-procedure. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive an tmos GATT_MSG_EVENT message. + * The type of the message will be either ATT_READ_MULTI_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_MULTI_RSP + * (with SUCCESS or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_ReadMultiCharValues( uint16_t connHandle, attReadMultiReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to write a Characteristic Value + * to a server when the client knows the Characteristic Value + * Handle and the client does not need an acknowledgement that + * the write was successfully performed. This sub-procedure + * only writes the first (ATT_MTU ?3) octets of a Characteristic + * Value. This sub-procedure can not be used to write a long + * characteristic; instead the Write Long Characteristic Values + * sub-procedure should be used. + * + * The ATT Write Command is used for this sub-procedure. The + * Attribute Handle parameter shall be set to the Characteristic + * Value Handle. The Attribute Value parameter shall be set to + * the new Characteristic Value. + * + * No response will be sent to the calling application task for this + * sub-procedure. If the Characteristic Value write request is the + * wrong size, or has an invalid value as defined by the profile, + * then the write will not succeed and no error will be generated + * by the server. + * + * @param connHandle - connection to use + * @param pReq - pointer to command to be sent + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_WriteNoRsp( uint16_t connHandle, attWriteReq_t *pReq ); + +/** + * @brief This sub-procedure is used to write a Characteristic Value + * to a server when the client knows the Characteristic Value + * Handle and the ATT Bearer is not encrypted. This sub-procedure + * shall only be used if the Characteristic Properties authenticated + * bit is enabled and the client and server device share a bond as + * defined in the GAP. + * + * This sub-procedure only writes the first (ATT_MTU ?15) octets + * of an Attribute Value. This sub-procedure cannot be used to + * write a long Attribute. + * + * The ATT Write Command is used for this sub-procedure. The + * Attribute Handle parameter shall be set to the Characteristic + * Value Handle. The Attribute Value parameter shall be set to + * the new Characteristic Value authenticated by signing the + * value, as defined in the Security Manager. + * + * No response will be sent to the calling application task for this + * sub-procedure. If the authenticated Characteristic Value that is + * written is the wrong size, or has an invalid value as defined by + * the profile, or the signed value does not authenticate the client, + * then the write will not succeed and no error will be generated by + * the server. + * + * @param connHandle - connection to use + * @param pReq - pointer to command to be sent + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleLinkEncrypted: Connection is already encrypted.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_SignedWriteNoRsp( uint16_t connHandle, attWriteReq_t *pReq ); + +/** + * @brief This sub-procedure is used to write a characteristic value + * to a server when the client knows the characteristic value + * handle. This sub-procedure only writes the first (ATT_MTU-3) + * octets of a characteristic value. This sub-procedure can not + * be used to write a long attribute; instead the Write Long + * Characteristic Values sub-procedure should be used. + * + * The ATT Write Request is used in this sub-procedure. The + * Attribute Handle parameter shall be set to the Characteristic + * Value Handle. The Attribute Value parameter shall be set to + * the new characteristic. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive an tmos GATT_MSG_EVENT message. + * The type of the message will be either ATT_WRITE_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_WRITE_RSP + * (with SUCCESS or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_WriteCharValue( uint16_t connHandle, attWriteReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to write a Characteristic Value to + * a server when the client knows the Characteristic Value Handle + * but the length of the Characteristic Value is longer than can + * be sent in a single Write Request Attribute Protocol message. + * + * The ATT Prepare Write Request and Execute Write Request are + * used to perform this sub-procedure. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_PREPARE_WRITE_RSP, + * ATT_EXECUTE_WRITE_RSP or ATT_ERROR_RSP (if an error occurred on + * the server). + * + * @note This sub-procedure is complete when either ATT_PREPARE_WRITE_RSP + * (with bleTimeout status), ATT_EXECUTE_WRITE_RSP + * (with SUCCESS or bleTimeout status), or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @note The 'pReq->pValue' pointer will be freed when the sub-procedure is complete. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_WriteLongCharValue( uint16_t connHandle, attPrepareWriteReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to write a Characteristic Value to + * a server when the client knows the Characteristic Value Handle, + * and assurance is required that the correct Characteristic Value + * is going to be written by transferring the Characteristic Value + * to be written in both directions before the write is performed. + * This sub-procedure can also be used when multiple values must + * be written, in order, in a single operation. + * + * The sub-procedure has two phases, the first phase prepares the + * characteristic values to be written. Once this is complete, + * the second phase performs the execution of all of the prepared + * characteristic value writes on the server from this client. + * + * In the first phase, the ATT Prepare Write Request is used. + * In the second phase, the attribute protocol Execute Write + * Request is used. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_PREPARE_WRITE_RSP, + * ATT_EXECUTE_WRITE_RSP or ATT_ERROR_RSP (if an error occurred on + * the server). + * + * @note This sub-procedure is complete when either ATT_PREPARE_WRITE_RSP + * (with bleTimeout status), ATT_EXECUTE_WRITE_RSP + * (with SUCCESS or bleTimeout status), or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @note The 'pReqs' pointer will be freed when the sub-procedure is complete. + * + * @param connHandle - connection to use + * @param pReqs - pointer to requests to be sent + * @param numReqs - number of requests in pReq + * @param flags - execute write request flags + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_ReliableWrites( uint16_t connHandle, attPrepareWriteReq_t *pReqs, uint8_t numReqs, + uint8_t flags, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to read a characteristic descriptor + * from a server when the client knows the characteristic descriptor + * declaration's Attribute handle. + * + * The ATT Read Request is used for this sub-procedure. The Read + * Request is used with the Attribute Handle parameter set to the + * characteristic descriptor handle. The Read Response returns the + * characteristic descriptor value in the Attribute Value parameter. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive an tmos GATT_MSG_EVENT message. + * The type of the message will be either ATT_READ_RSP or + * ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_RSP + * (with SUCCESS or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_ReadCharDesc( uint16_t connHandle, attReadReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to read a characteristic descriptor + * from a server when the client knows the characteristic descriptor + * declaration's Attribute handle and the length of the characteristic + * descriptor declaration is longer than can be sent in a single Read + * Response attribute protocol message. + * + * The ATT Read Blob Request is used to perform this sub-procedure. + * The Attribute Handle parameter shall be set to the characteristic + * descriptor handle. The Value Offset parameter shall be the offset + * within the characteristic descriptor to be read. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_READ_BLOB_RSP or + * ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_READ_BLOB_RSP + * (with bleProcedureComplete or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_ReadLongCharDesc( uint16_t connHandle, attReadBlobReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to write a characteristic + * descriptor value to a server when the client knows the + * characteristic descriptor handle. + * + * The ATT Write Request is used for this sub-procedure. The + * Attribute Handle parameter shall be set to the characteristic + * descriptor handle. The Attribute Value parameter shall be + * set to the new characteristic descriptor value. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive an tmos GATT_MSG_EVENT message. + * The type of the message will be either ATT_WRITE_RSP + * or ATT_ERROR_RSP (if an error occurred on the server). + * + * @note This sub-procedure is complete when either ATT_WRITE_RSP + * (with SUCCESS or bleTimeout status) or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_WriteCharDesc( uint16_t connHandle, attWriteReq_t *pReq, uint8_t taskId ); + +/** + * @brief This sub-procedure is used to write a Characteristic Value to + * a server when the client knows the Characteristic Value Handle + * but the length of the Characteristic Value is longer than can + * be sent in a single Write Request Attribute Protocol message. + * + * The ATT Prepare Write Request and Execute Write Request are + * used to perform this sub-procedure. + * + * If the return status from this function is SUCCESS, the calling + * application task will receive multiple tmos GATT_MSG_EVENT messages. + * The type of the messages will be either ATT_PREPARE_WRITE_RSP, + * ATT_EXECUTE_WRITE_RSP or ATT_ERROR_RSP (if an error occurred on + * the server). + * + * @note This sub-procedure is complete when either ATT_PREPARE_WRITE_RSP + * (with bleTimeout status), ATT_EXECUTE_WRITE_RSP + * (with SUCCESS or bleTimeout status), or ATT_ERROR_RSP + * (with SUCCESS status) is received by the calling application task. + * + * @note The 'pReq->pValue' pointer will be freed when the sub-procedure is complete. + * + * @param connHandle - connection to use + * @param pReq - pointer to request to be sent + * @param taskId - task to be notified of response + * + * @return SUCCESS: Request was sent successfully.
+ * INVALIDPARAMETER: Invalid connection handle or request field.v + * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A response is pending with this server.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleTimeout: Previous transaction timed out.
+ */ +extern bStatus_t GATT_WriteLongCharDesc( uint16_t connHandle, attPrepareWriteReq_t *pReq, uint8_t taskId ); + +/** + * @brief GATT implementation of the allocator functionality. + * + * @note This function should only be called by GATT and the upper layer protocol/application. + * + * @param connHandle - connection that message is to be sent on. + * @param opcode - opcode of message that buffer to be allocated for. + * @param size - number of bytes to allocate from the heap. + * @param pSizeAlloc - number of bytes allocated for the caller from the heap. + * @param flag - . + * + * @return pointer to the heap allocation; NULL if error or failure. + */ +extern void *GATT_bm_alloc( uint16_t connHandle, uint8_t opcode, uint16_t size, uint16_t *pSizeAlloc, uint8_t flag ); + +/** + * @brief GATT implementation of the de-allocator functionality. + * + * @param pMsg - pointer to GATT message containing the memory to free. + * @param opcode - opcode of the message + * + * @return none + */ +extern void GATT_bm_free( gattMsg_t *pMsg, uint8_t opcode ); + +/** + * @brief Register a service's attribute list and callback functions with + * the GATT Server Application. + * + * @param pAttrs - Array of attribute records to be registered + * @param numAttrs - Number of attributes in array + * @param encKeySize - Minimum encryption key size required by service (7-16 bytes) + * @param pServiceCBs - Service callback function pointers + * + * @return SUCCESS: Service registered successfully.
+ * INVALIDPARAMETER: Invalid service fields.
+ * FAILURE: Not enough attribute handles available.
+ * bleMemAllocError: Memory allocation error occurred.
+ * bleInvalidRange: Encryption key size's out of range.
+ */ +extern bStatus_t GATTServApp_RegisterService( gattAttribute_t *pAttrs, uint16_t numAttrs, + uint8_t encKeySize, gattServiceCBs_t *pServiceCBs ); + +/** + * @brief Add function for the GATT Service. + * + * @param services - services to add. This is a bit map and can + * contain more than one service. + * + * @return SUCCESS: Service added successfully.
+ * INVALIDPARAMETER: Invalid service field.
+ * FAILURE: Not enough attribute handles available.
+ * bleMemAllocError: Memory allocation error occurred.
+ */ +extern bStatus_t GATTServApp_AddService( uint32_t services ); + +/** + * @brief Deregister a service's attribute list and callback functions from + * the GATT Server Application. + * + * @note It's the caller's responsibility to free the service attribute + * list returned from this API. + * + * @param handle - handle of service to be deregistered + * @param p2pAttrs - pointer to array of attribute records (to be returned) + * + * @return SUCCESS: Service deregistered successfully.
+ * FAILURE: Service not found.
+ */ +extern bStatus_t GATTServApp_DeregisterService( uint16_t handle, gattAttribute_t **p2pAttrs ); + +/** + * @brief Initialize the client characteristic configuration table. + * + * @note Each client has its own instantiation of the ClientCharacteristic Configuration. + * Reads/Writes of the Client Characteristic Configuration only only affect the + * configuration of that client. + * + * @param connHandle - connection handle (0xFFFF for all connections). + * @param charCfgTbl - client characteristic configuration table. + * + * @return none + */ +extern void GATTServApp_InitCharCfg( uint16_t connHandle, gattCharCfg_t *charCfgTbl ); + +/** + * @brief Send out a Service Changed Indication. + * + * @param connHandle - connection to use + * @param taskId - task to be notified of confirmation + * + * @return SUCCESS: Indication was sent successfully.
+ * FAILURE: Service Changed attribute not found.
+ * INVALIDPARAMETER: Invalid connection handle or request field.
+ * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
+ * bleNotConnected: Connection is down.
+ * blePending: A confirmation is pending with this client.
+ */ +extern bStatus_t GATTServApp_SendServiceChangedInd( uint16_t connHandle, uint8_t taskId ); + +/** + * @brief Read the client characteristic configuration for a given client. + * + * @note Each client has its own instantiation of the Client Characteristic Configuration. + * Reads of the Client Characteristic Configuration only shows the configuration + * for that client. + * + * @param connHandle - connection handle. + * @param charCfgTbl - client characteristic configuration table. + * + * @return attribute value + */ +extern uint16_t GATTServApp_ReadCharCfg( uint16_t connHandle, gattCharCfg_t *charCfgTbl ); + +/** + * @brief Write the client characteristic configuration for a given client. + * + * @note Each client has its own instantiation of the Client Characteristic Configuration. + * Writes of the Client Characteristic Configuration only only affect the + * configuration of that client. + * + * @param connHandle - connection handle. + * @param charCfgTbl - client characteristic configuration table. + * @param value - attribute new value. + * + * @return Success or Failure + */ +extern uint8_t GATTServApp_WriteCharCfg( uint16_t connHandle, gattCharCfg_t *charCfgTbl, uint16_t value ); + +/** + * @brief Process the client characteristic configuration + * write request for a given client. + * + * @param connHandle - connection message was received on. + * @param pAttr - pointer to attribute. + * @param pValue - pointer to data to be written. + * @param len - length of data. + * @param offset - offset of the first octet to be written. + * @param validCfg - valid configuration. + * + * @return Success or Failure + */ +extern bStatus_t GATTServApp_ProcessCCCWriteReq( uint16_t connHandle, gattAttribute_t *pAttr, + uint8_t *pValue, uint16_t len, uint16_t offset, uint16_t validCfg ); + +/** + * @brief Set a GAP GATT Server parameter. + * + * @param param - Profile parameter ID
+ * @param len - length of data to right + * @param value - pointer to data to write. This is dependent on + * the parameter ID and WILL be cast to the appropriate + * data type (example: data type of uint16_t will be cast to + * uint16_t pointer).
+ * + * @return bStatus_t + */ +extern bStatus_t GGS_SetParameter( uint8_t param, uint8_t len, void *value ); + +/** + * @brief Get a GAP GATT Server parameter. + * + * @param param - Profile parameter ID
+ * @param value - pointer to data to put. This is dependent on + * the parameter ID and WILL be cast to the appropriate + * data type (example: data type of uint16_t will be cast to + * uint16_t pointer).
+ * + * @return bStatus_t + */ +extern bStatus_t GGS_GetParameter( uint8_t param, void *value ); + +/** + * @brief Add function for the GAP GATT Service. + * + * @param services - services to add. This is a bit map and can + * contain more than one service. + * + * @return SUCCESS: Service added successfully.
+ * INVALIDPARAMETER: Invalid service field.
+ * FAILURE: Not enough attribute handles available.
+ * bleMemAllocError: Memory allocation error occurred.
+ */ +extern bStatus_t GGS_AddService( uint32_t services ); + +/*------------------------------------------------------------------- + * FUNCTIONS - Initialization and Configuration + */ + +/** + * @brief Set a GAP Parameter value. Use this function to change the default GAP parameter values. + * + * @param paramID - parameter ID: @ref GAP_PARAMETER_ID_DEFINES + * @param paramValue - new param value + * + * @return SUCCESS or INVALIDPARAMETER (invalid paramID) + */ +extern bStatus_t GAP_SetParamValue( uint16_t paramID, uint16_t paramValue ); + +/** + * @brief Get a GAP Parameter value. + * + * @note This function is the same as GAP_PasskeyUpdate(), except that + * the passkey is passed in as a non-string format. + * + * @param paramID - parameter ID: @ref GAP_PARAMETER_ID_DEFINES + * + * @return GAP Parameter value or 0xFFFF if invalid + */ +extern uint16_t GAP_GetParamValue( uint16_t paramID ); + +/** + * @brief Setup the device's address type. If ADDRTYPE_PRIVATE_RESOLVE is selected, + * the address will change periodically. + * + * @param addrType - @ref GAP_ADDR_TYPE_DEFINES + * @param pStaticAddr - Only used with ADDRTYPE_STATIC or ADDRTYPE_PRIVATE_NONRESOLVE type + * NULL to auto generate otherwise the application can specify the address value + * + * @return SUCCESS: address type updated,
+ * bleNotReady: Can't be called until GAP_DeviceInit() is called + * and the init process is completed + * bleIncorrectMode: can't change with an active connection,or INVALIDPARAMETER + * If return value isn't SUCCESS, the address type remains the same as before this call. + */ +extern bStatus_t GAP_ConfigDeviceAddr( uint8_t addrType, uint8_t *pStaticAddr ); + +/** + * @brief Resolves a private address against an IRK. + * + * @param(in) pIRK - pointer to the IRK + * @param(in) pAddr - pointer to the Resolvable Private address + * + * @param(out) pIRK + * @param(out) pAddr + * + * @return SUCCESS: match,
+ * FAILURE: don't match,
+ * INVALIDPARAMETER: parameters invalid
+ */ +extern bStatus_t GAP_ResolvePrivateAddr( uint8_t *pIRK, uint8_t *pAddr ); + +/** + * @brief Setup or change advertising and scan response data. + * + * @note if the return status from this function is SUCCESS,the task isn't complete + * until the GAP_ADV_DATA_UPDATE_DONE_EVENT is sent to the calling application task. + * + * @param taskID - task ID of the app requesting the change + * @param adType - TRUE - advertisement data, FALSE - scan response data + * @param dataLen - Octet length of advertData + * @param pAdvertData - advertising or scan response data + * + * @return SUCCESS: data accepted + * bleIncorrectMode: invalid profile role + */ +extern bStatus_t GAP_UpdateAdvertisingData( uint8_t taskID, uint8_t adType, uint16_t dataLen, uint8_t *pAdvertData ); + +/*------------------------------------------------------------------- + * FUNCTIONS - GAP Bond API + */ +/** + * @brief Set a GAP Bond Manager parameter. + * + * @note You can call this function with a GAP Parameter ID and it will set the GAP Parameter. + * + * @param param - Profile parameter ID: @ref GAPBOND_PROFILE_PARAMETERS + * @param len - length of data to write + * @param pValue - pointer to data to write. This is dependent on + * the parameter ID and WILL be cast to the appropriate + * data type (example: data type of uint16_t will be cast to + * uint16_t pointer). + * + * @return SUCCESS or INVALIDPARAMETER (invalid paramID) + */ +extern bStatus_t GAPBondMgr_SetParameter( uint16_t param, uint8_t len, void *pValue ); + +/** + * @brief Get a GAP Bond Manager parameter. + * + * @note You can call this function with a GAP Parameter ID and it will get a GAP Parameter. + * + * @param param - Profile parameter ID: @ref GAPBOND_PROFILE_PARAMETERS + * @param pValue - pointer to location to get the value. This is dependent on + * the parameter ID and WILL be cast to the appropriate data type. + * (example: data type of uint16_t will be cast to uint16_t pointer) + * + * @return SUCCESS or INVALIDPARAMETER (invalid paramID) + */ +extern bStatus_t GAPBondMgr_GetParameter( uint16_t param, void *pValue ); + +/** + * @brief Respond to a passcode request. + * + * @param connectionHandle - connection handle of the connected device or 0xFFFF if all devices in database. + * @param status - SUCCESS if passcode is available, otherwise see @ref SMP_PAIRING_FAILED_DEFINES. + * @param passcode - integer value containing the passcode. + * + * @return SUCCESS - bond record found and changed + * bleIncorrectMode - Link not found. + */ +extern bStatus_t GAPBondMgr_PasscodeRsp( uint16_t connectionHandle, uint8_t status, uint32_t passcode ); + +/** + * @brief Respond to a passcode request. + * + * @param connHandle - connection handle of the connected device or 0xFFFF if all devices in database. + * @param status - SUCCESS if oob data is available, otherwise see @ref SMP_PAIRING_FAILED_DEFINES. + * @param oob - containing the oob data. + * @param c_peer - containing the peer confirm. + * + * @return SUCCESS - bond record found and changed + * bleIncorrectMode - Link not found. + */ +extern bStatus_t GAPBondMgr_OobRsp( uint16_t connHandle, uint8_t status, uint8_t *oob, uint8_t * c_peer ); + +/** + * @brief Initialization function for the ecc-function callback. + * + * @param pEcc - callback registration Structure @ref gapEccCBs_t. + * + * @return null. + */ +extern void GAPBondMgr_EccInit( gapEccCBs_t *pEcc ); + +/** + * @brief Send a security request + * + * @param connHandle - connection handle + * + * @return SUCCESS: will send + * bleNotConnected: Link not found + * bleIncorrectMode: wrong GAP role, must be a Peripheral Role + */ +extern bStatus_t GAPBondMgr_PeriSecurityReq( uint16_t connHandle ); + +/*------------------------------------------------------------------- + * FUNCTIONS - GAPRole API + */ +/** + * @brief Set a GAP Role parameter. + * + * @note You can call this function with a GAP Parameter ID and it will set a GAP Parameter. + * + * @param param - Profile parameter ID: @ref GAPROLE_PROFILE_PARAMETERS + * @param len - length of data to write + * @param pValue - pointer to data to write. This is dependent on the parameter ID and + * WILL be cast to the appropriate data type (example: data type of uint16_t + * will be cast to uint16_t pointer). + * + * @return SUCCESS or INVALIDPARAMETER (invalid paramID) + */ +extern bStatus_t GAPRole_SetParameter( uint16_t param, uint16_t len, void *pValue ); + +/** + * @brief Get a GAP Role parameter. + * + * @note You can call this function with a GAP Parameter ID and it will get a GAP Parameter. + * + * @param param - Profile parameter ID: @ref GAPROLE_PROFILE_PARAMETERS + * @param pValue - pointer to location to get the value. This is dependent on + * the parameter ID and WILL be cast to the appropriate + * data type (example: data type of uint16_t will be cast to + * uint16_t pointer). + * + * @return SUCCESS or INVALIDPARAMETER (invalid paramID) + */ +extern bStatus_t GAPRole_GetParameter( uint16_t param, void *pValue ); + +/** + * @brief Terminates the existing connection. + * + * @return SUCCESS or bleIncorrectMode + */ +extern bStatus_t GAPRole_TerminateLink( uint16_t connHandle ); + +/** + * @brief Read Rssi Cmd. + * + * @param connHandle - connection handle + * + * @return bStatus_t: HCI Error Code.
+ * + */ +extern bStatus_t GAPRole_ReadRssiCmd( uint16_t connHandle ); + +/** + * @brief used to synchronize with a periodic advertising train from an advertiser and + * begin receiving periodic advertising packets. + * + * @param pSync - sync parameters@ gapCreateSync_t + * + * @return bStatus_t: HCI Error Code.
+ * + */ +extern bStatus_t GAPRole_CreateSync( gapCreateSync_t *pSync ); + +/** + * @brief used to cancel the HCI_LE_Periodic_Advertising_Create_Sync command while + * it is pending. + * + * @param None. + * + * @return bStatus_t: HCI Error Code.
+ * + */ +extern bStatus_t GAPRole_CancelSync( void ); + +/** + * @brief used to stop reception of the periodic advertising train identified + * by the Sync_Handle parameter. + * + * @param syncHandle-identifying the periodic advertising train + * + * @return bStatus_t: HCI Error Code.
+ * + */ +extern bStatus_t GAPRole_TerminateSync( uint16_t syncHandle ); + +/** + * @brief Update the link connection parameters. + * + * @param connHandle - connection handle + * @param connIntervalMin - minimum connection interval in 1.25ms units + * @param connIntervalMax - maximum connection interval in 1.25ms units + * @param connLatency - number of LL latency connection events + * @param connTimeout - connection timeout in 10ms units + * + * @return SUCCESS: Connection update started started.
+ * bleIncorrectMode: No connection to update.
+ */ +extern bStatus_t GAPRole_UpdateLink( uint16_t connHandle, uint16_t connIntervalMin, + uint16_t connIntervalMax, uint16_t connLatency, uint16_t connTimeout ); + +/** + * @brief Update the connection phy. + * + * @param connHandle - connection handle + * @param all_phys - a bit field that allows the Host to specify, for each direction + * set BIT0:The Host has no preference among the transmitter PHYs supported by the Controller + * set BIT1:The Host has no preference among the receiver PHYs supported by the Controller + * @param tx_phys - a bit field that indicates the transmitter PHYs.(GAP_PHY_BIT_TYPE) + * @param rx_phys - a bit field that indicates the receiver PHYs.(GAP_PHY_BIT_TYPE) + * @param phy_options - preferred coding when transmitting on the LE Coded PHY(GAP_PHY_OPTIONS_TYPE) + * + * @return SUCCESS: PHY update started started .
+ * bleIncorrectMode: No connection to update.
+ */ +extern bStatus_t GAPRole_UpdatePHY( uint16_t connHandle, uint8_t all_phys, uint8_t tx_phys,\ + uint8_t rx_phys, uint16_t phy_options ); + +/** + * @brief used to allow the Host to specify the privacy mode to be used for a given entry on the resolving list. + * + * @note This command shall not be used when address resolution is enabled in the Controller and: + * Advertising (other than periodic advertising) is enabled, + * Scanning is enabled, or + * an GAPRole_CentralEstablishLink, or GAPRole_CreateSync command is pending. + * + * @param addrTypePeer - 0x00:Public Identity Address 0x01:Random (static) Identity Address + * @param peerAddr - Public Identity Address or Random (static) Identity Address of the advertiser + * @param privacyMode - 0x00:Use Network Privacy Mode for this peer device (default) + * 0x01:Use Device Privacy Mode for this peer device + * + * @return Command Status. + * + */ +extern bStatus_t GAPRole_SetPrivacyMode( uint8_t addrTypePeer, uint8_t *peerAddr, uint8_t privacyMode ); + +/** + * @brief used to set the path loss threshold reporting parameters. + * + * @param pParm - set path loss parameters@ gapRoleSetPathLossReporting_t + * + * @return Command Status. + * + */ +extern bStatus_t GAPRole_SetPathLossReporting( gapRoleSetPathLossReporting_t *pParm ); + +/** + * @brief used to set power level management. + * + * @param pParm - set power level parameters@ gapRolePowerlevelManagement_t + * + * @return Command Status. + * + */ +extern bStatus_t GAPRole_SetPowerlevel( gapRolePowerlevelManagement_t *pParm ); + +/*------------------------------------------------------------------- + * FUNCTIONS - BROADCASTER_PROFILE_API Broadcaster Profile API + */ +/** + * + * @brief Initialization function for the GAP Role Task. + * + * @param None. + * + * @return SUCCESS,bleInvalidRange + */ +extern bStatus_t GAPRole_BroadcasterInit( void ); + +/** + * @brief Does the device initialization. Only call this function once. + * + * @param pAppCallbacks - pointer to application callbacks. + * + * @return SUCCESS or bleAlreadyInRequestedMode + */ +extern bStatus_t GAPRole_BroadcasterStartDevice( gapRolesBroadcasterCBs_t *pAppCallbacks ); + +/** + * @brief Does the Broadcaster receive scan request call initialization. + * + * @param pAppCallbacks - pointer to application callbacks. + * + * @return None + */ +extern void GAPRole_BroadcasterSetCB( gapRolesBroadcasterCBs_t *pAppCallbacks ); + +/*------------------------------------------------------------------- + * FUNCTIONS - OBSERVER_PROFILE_API Observer Profile API + */ +/** + * @internal + * + * @brief Observer Profile Task initialization function. + * + * @param None. + * + * @return SUCCESS,bleInvalidRange + */ +extern bStatus_t GAPRole_ObserverInit( void ); + +/** + * @brief Start the device in Observer role. This function is typically + * called once during system startup. + * + * @param pAppCallbacks - pointer to application callbacks + * + * @return SUCCESS: Operation successful.
+ * bleAlreadyInRequestedMode: Device already started.
+ */ +extern bStatus_t GAPRole_ObserverStartDevice( gapRoleObserverCB_t *pAppCallbacks ); + +/** + * @brief Start a device discovery scan. + * + * @param mode - discovery mode: @ref GAP_DEVDISC_MODE_DEFINES + * @param activeScan - TRUE to perform active scan + * @param whiteList - TRUE to only scan for devices in the white list + * + * @return SUCCESS: Discovery scan started.
+ * bleIncorrectMode: Invalid profile role.
+ * bleAlreadyInRequestedMode: Not available.
+ */ +extern bStatus_t GAPRole_ObserverStartDiscovery( uint8_t mode, uint8_t activeScan, uint8_t whiteList ); + +/** + * @brief Cancel a device discovery scan. + * + * @return SUCCESS: Cancel started.
+ * bleInvalidTaskID: Not the task that started discovery.
+ * bleIncorrectMode: Not in discovery mode.
+ */ +extern bStatus_t GAPRole_ObserverCancelDiscovery( void ); + +/*------------------------------------------------------------------- + * FUNCTIONS - PERIPHERAL_PROFILE_API Peripheral Profile API + */ +/** + * @internal + * + * @brief Initialization function for the GAP Role Task. + * This is called during initialization and should contain + * any application specific initialization (ie. hardware + * initialization/setup, table initialization, power up + * notificaiton ... ). + * + * @param None. + * + * @return SUCCESS,bleInvalidRange + */ +extern bStatus_t GAPRole_PeripheralInit( void ); + +/** + * @brief Does the device initialization. Only call this function once. + * + * @param pAppCallbacks - pointer to application callbacks. + * + * @return SUCCESS or bleAlreadyInRequestedMode + */ +extern bStatus_t GAPRole_PeripheralStartDevice( uint8_t taskid, gapBondCBs_t *pCB, gapRolesCBs_t *pAppCallbacks ); + +/** + * @brief Update the parameters of an existing connection + * + * @param connHandle - the connection Handle + * @param connIntervalMin - minimum connection interval in 1.25ms units + * @param connIntervalMax - maximum connection interval in 1.25ms units + * @param latency - the new slave latency + * @param connTimeout - the new timeout value + * @param taskId - taskID will recv L2CAP_SIGNAL_EVENT message + * + * @return SUCCESS, bleNotConnected or bleInvalidRange + */ +extern bStatus_t GAPRole_PeripheralConnParamUpdateReq( uint16_t connHandle, uint16_t connIntervalMin, + uint16_t connIntervalMax, uint16_t latency, uint16_t connTimeout, uint8_t taskId ); + +/*------------------------------------------------------------------- + * FUNCTIONS - CENTRAL_PROFILE_API Central Profile API + */ +/** + * @internal + * + * @brief Central Profile Task initialization function. + * + * @param None. + * + * @return SUCCESS,bleInvalidRange + */ +extern bStatus_t GAPRole_CentralInit( void ); + +/** + * @brief Start the device in Central role. This function is typically + * called once during system startup. + * + * @param pAppCallbacks - pointer to application callbacks + * + * @return SUCCESS: Operation successful.
+ * bleAlreadyInRequestedMode: Device already started.
+ */ +extern bStatus_t GAPRole_CentralStartDevice( uint8_t taskid, gapBondCBs_t *pCB, gapCentralRoleCB_t *pAppCallbacks ); + +/** + * @brief Start a device discovery scan. + * + * @param mode - discovery mode: @ref GAP_DEVDISC_MODE_DEFINES + * @param activeScan - TRUE to perform active scan + * @param whiteList - TRUE to only scan for devices in the white list + * + * @return SUCCESS: Discovery scan started.
+ * bleIncorrectMode: Invalid profile role.
+ * bleAlreadyInRequestedMode: Not available.
+ */ +extern bStatus_t GAPRole_CentralStartDiscovery( uint8_t mode, uint8_t activeScan, uint8_t whiteList ); + +/** + * @brief Cancel a device discovery scan. + * + * @return SUCCESS: Cancel started.
+ * bleInvalidTaskID: Not the task that started discovery.
+ * bleIncorrectMode: Not in discovery mode.
+ */ +extern bStatus_t GAPRole_CentralCancelDiscovery( void ); + +/** + * @brief This API is called by the Central to update the Host data channels + * initiating an Update Data Channel control procedure. + * + * @note While it isn't specified,it is assumed that the Host expects an + * update channel map on all active connections and periodic advertise. + * + * input parameters + * + * @param chanMap - A five byte array containing one bit per data channel + * where a 1 means the channel is "used". + * + * @return SUCCESS + */ +extern void GAPRole_SetHostChanClassification( uint8_t *chanMap ); + +/** + * @brief Establish a link to a peer device. + * + * @param highDutyCycle - TRUE to high duty cycle scan, FALSE if not + * @param whiteList - determines use of the white list: TRUE-enable + * @param addrTypePeer - address type of the peer device: @ref GAP_ADDR_TYPE_DEFINES + * @param peerAddr - peer device address + * + * @return SUCCESS: started establish link process.
+ * bleIncorrectMode: invalid profile role.
+ * bleNotReady: a scan is in progress.
+ * bleAlreadyInRequestedMode: can't process now.
+ * bleNoResources: too many links.
+ */ +extern bStatus_t GAPRole_CentralEstablishLink( uint8_t highDutyCycle, uint8_t whiteList, uint8_t addrTypePeer, uint8_t *peerAddr ); + +/*------------------------------------------------------------------- + * FUNCTIONS - RF_PHY Profile API + */ + +/** + * @brief RF_PHY Profile Task initialization function. + * + * @param None. + * + * @return 0 - success. + */ +extern bStatus_t RF_RoleInit( void ); + +/** + * @brief rf config. + * + * @param pConfig - rf config parameters + * + * @return 0 - success. + */ +extern bStatus_t RF_Config( rfConfig_t *pConfig ); + +/** + * @brief rx mode. + * + * @param txBuf - rx mode tx data + * @param txLen - rx mode tx length(0-251) + * @param pktRxType - rx mode rx package type + * broadcast type(0xFF):receive all matching types, + * others:receive match type or broadcast type + * @param pktTxType - rx mode tx package type(auto mode) + * broadcast type(0xFF):received by all matching types; + * others:only received by matching type + * + * @return 0 - success. + */ +extern bStatus_t RF_Rx( uint8_t *txBuf, uint8_t txLen, uint8_t pktRxType, uint8_t pktTxType ); + +/** + * @brief tx mode. + * + * @param txBuf - tx mode tx data + * @param txLen - tx mode tx length(0-251) + * @param pktTxType - tx mode tx package type + * broadcast type(0xFF):received by all matching types; + * others:only received by matching type + * @param pktRxType - tx mode rx package type(auto mode) + * broadcast type(0xFF):receive all matching types, + * others:receive match type or broadcast type + * + * @return 0 - success. + */ +extern bStatus_t RF_Tx( uint8_t *txBuf, uint8_t txLen, uint8_t pktTxType, uint8_t pktRxType ); + +/** + * @brief shut down,stop tx/rx mode. + * + * @param None. + * + * @return 0 - success. + */ +extern bStatus_t RF_Shut( void ); + +/** + * @brief rf mode set radio channel/frequency. + * + * @param channel. + * + * @return 0 - success. + */ +extern void RF_SetChannel( uint32_t channel ); + +/** + * @brief shut down rf frequency hopping + * + * @param None. + * + * @return None. + */ +extern void RF_FrequencyHoppingShut( void ); + +/** + * @brief + * + * @param resendCount - Maximum count of sending HOP_TX pdu,0 = unlimited. + * + * @return 0 - success. + */ +extern uint8_t RF_FrequencyHoppingTx( uint8_t resendCount ); + +/** + * @brief + * + * @param timeoutMS - Maximum time to wait for receiving HOP_TX pdu(Time = n * 1mSec),0 = unlimited. + * + * @return 0 - success.1-fail.2-LLEMode error(shall AUTO) + */ +extern uint8_t RF_FrequencyHoppingRx( uint32_t timeoutMS ); + +/** + * @brief Erase FH bonded device + * + * @param None. + * + * @return None. + */ +extern void RF_BondingErase( void ); + +/** + * @brief single channel mode. + * + * @param ch - rf channel,f=2402+ch*2 MHz, ch=0,...,39 + * + * @return 0 - success. + */ +extern bStatus_t LL_SingleChannel( uint8_t ch ); + +/** + * @brief used to stop any test which is in progress. + * + * @param(in) pPktNum - null + * + * @param(out) the number of received packets. + * + * @return 0 - success. + */ +extern bStatus_t LL_TestEnd( uint8_t *pPktNum ); + +/** + * @brief used to start a test where the DUT receives test reference packets at a fixed interval + * + * input parameters + * + * @param opcode = 0x201D + * pParm0 - RX_Channel + * + * opcode = 0x2033 + * pParm0 - RX_Channel + * pParm1 - PHY + * pParm2 - Modulation_Index + * + * @return 0 - success. + */ +extern bStatus_t API_LE_ReceiverTestCmd( uint8_t *pParm, uint16_t opcode ); + +/** + * @brief used to start a test where the DUT generates test reference packets at a fixed interval + * + * @param opcode = 0x201E + * pParm 0 - TX_Channel + * pParm 1 - Test_Data_Length + * pParm 2 - Packet_Payload + * + * opcode = 0x2034 + * pParm 0 - TX_Channel + * pParm 1 - Test_Data_Length + * pParm 2 - Packet_Payload + * pParm 3 - PHY + * + * @return 0 - success. + */ +extern bStatus_t API_LE_TransmitterTestCmd( uint8_t *pParm, uint16_t opcode ); + +/** + * @brief used to stop any test which is in progress + * + * @param None + * + * @return 0 - success. + */ +extern bStatus_t API_LE_TestEndCmd( void ); + +/** + * @brief used to set sensitivity level + * + * @param None + * + * @return None. + */ +extern void RFEND_SetSensitivity( void ); + +/** + * @brief used to set rf TxCtune value + * + * @param pParm(in) - Must provide length of parameter followed by 6 bytes parameter + * + * @return Command Status. + */ +extern bStatus_t RFEND_TXCtuneSet( uint8_t *pParm ); + +/** + * @brief used to get rf TxCtune value + * + * @param pParm(out) - length of parameter(6) followed by 6 bytes parameter + * + * @return Command Status. + */ +extern bStatus_t RFEND_TXCtuneGet( uint8_t *pParm ); + +/* + * END @ Profile API + */ +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif diff --git a/CH5xx_ble_firmware_library/BLE/LIBCH58xBLE.a b/CH5xx_ble_firmware_library/BLE/LIBCH58xBLE.a new file mode 100644 index 0000000..542bbc4 Binary files /dev/null and b/CH5xx_ble_firmware_library/BLE/LIBCH58xBLE.a differ diff --git a/CH5xx_ble_firmware_library/Ld/Link.ld b/CH5xx_ble_firmware_library/Ld/Link.ld new file mode 100644 index 0000000..a61dd5c --- /dev/null +++ b/CH5xx_ble_firmware_library/Ld/Link.ld @@ -0,0 +1,178 @@ +ENTRY( _start ) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 448K + RAM (xrw) : ORIGIN = 0x20003800, LENGTH = 32K +} + + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + + /* .vector : + { + *(.vector); + } >FLASH AT>FLASH */ + + .highcodelalign : + { + . = ALIGN(4); + PROVIDE(_highcode_lma = .); + } >FLASH AT>FLASH + + .highcode : + { + . = ALIGN(4); + PROVIDE(_highcode_vma_start = .); + *(.vector); + KEEP(*(SORT_NONE(.vector_handler))) + *(.highcode); + *(.highcode.*); + . = ALIGN(4); + PROVIDE(_highcode_vma_end = .); + } >RAM AT>FLASH + + .text : + { + . = ALIGN(4); + KEEP(*(SORT_NONE(.handle_reset))) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.sdata2.*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dalign : + { + . = ORIGIN(RAM) + MAX(0x800 , SIZEOF(.highcode)); + } >RAM AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + .stack ORIGIN(RAM)+LENGTH(RAM) : + { + . = ALIGN(4); + PROVIDE(_eusrstack = . ); + } >RAM +} + + + diff --git a/CH5xx_ble_firmware_library/RVMSIS/core_riscv.c b/CH5xx_ble_firmware_library/RVMSIS/core_riscv.c new file mode 100644 index 0000000..ac8238f --- /dev/null +++ b/CH5xx_ble_firmware_library/RVMSIS/core_riscv.c @@ -0,0 +1,306 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : core_riscv.c + * Author : WCH + * Version : V1.1.0 + * Date : 2021/06/06 + * Description : RISC-V Core Peripheral Access Layer Source File + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ +#include + +/* define compiler specific symbols */ +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + +#endif + + + +/********************************************************************* + * @fn __get_MSTATUS + * + * @brief Return the Machine Status Register + * + * @return mstatus value + */ +uint32_t __get_MSTATUS(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mstatus" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __set_MSTATUS + * + * @brief Set the Machine Status Register + * + * @param value - set mstatus value + * + * @return none + */ +void __set_MSTATUS(uint32_t value) +{ + __ASM volatile ("csrw mstatus, %0" : : "r" (value) ); +} + +/********************************************************************* + * @fn __get_MISA + * + * @brief Return the Machine ISA Register + * + * @return misa value + */ +uint32_t __get_MISA(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "misa" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __set_MISA + * + * @brief Set the Machine ISA Register + * + * @param value - set misa value + * + * @return none + */ +void __set_MISA(uint32_t value) +{ + __ASM volatile ("csrw misa, %0" : : "r" (value) ); +} + +/********************************************************************* + * @fn __get_MTVEC + * + * @brief Return the Machine Trap-Vector Base-Address Register + * + * @return mtvec value + */ +uint32_t __get_MTVEC(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mtvec" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __set_MTVEC + * + * @brief Set the Machine Trap-Vector Base-Address Register + * + * @param value - set mtvec value + * + * @return none + */ +void __set_MTVEC(uint32_t value) +{ + __ASM volatile ("csrw mtvec, %0" : : "r" (value) ); +} + +/********************************************************************* + * @fn __get_MSCRATCH + * + * @brief Return the Machine Seratch Register + * + * @return mscratch value + */ +uint32_t __get_MSCRATCH(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mscratch" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __set_MSCRATCH + * + * @brief Set the Machine Seratch Register + * + * @param value - set mscratch value + * + * @return none + */ +void __set_MSCRATCH(uint32_t value) +{ + __ASM volatile ("csrw mscratch, %0" : : "r" (value) ); +} + +/********************************************************************* + * @fn __get_MEPC + * + * @brief Return the Machine Exception Program Register + * + * @return mepc value + */ +uint32_t __get_MEPC(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mepc" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __set_MEPC + * + * @brief Set the Machine Exception Program Register + * + * @return mepc value + */ +void __set_MEPC(uint32_t value) +{ + __ASM volatile ("csrw mepc, %0" : : "r" (value) ); +} + +/********************************************************************* + * @fn __get_MCAUSE + * + * @brief Return the Machine Cause Register + * + * @return mcause value + */ +uint32_t __get_MCAUSE(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mcause" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __set_MEPC + * + * @brief Set the Machine Cause Register + * + * @return mcause value + */ +void __set_MCAUSE(uint32_t value) +{ + __ASM volatile ("csrw mcause, %0" : : "r" (value) ); +} + +/********************************************************************* + * @fn __get_MTVAL + * + * @brief Return the Machine Trap Value Register + * + * @return mtval value + */ +uint32_t __get_MTVAL(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mtval" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __set_MTVAL + * + * @brief Set the Machine Trap Value Register + * + * @return mtval value + */ +void __set_MTVAL(uint32_t value) +{ + __ASM volatile ("csrw mtval, %0" : : "r" (value) ); +} + +/********************************************************************* + * @fn __get_MVENDORID + * + * @brief Return Vendor ID Register + * + * @return mvendorid value + */ +uint32_t __get_MVENDORID(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mvendorid" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __get_MARCHID + * + * @brief Return Machine Architecture ID Register + * + * @return marchid value + */ +uint32_t __get_MARCHID(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "marchid" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __get_MIMPID + * + * @brief Return Machine Implementation ID Register + * + * @return mimpid value + */ +uint32_t __get_MIMPID(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mimpid" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __get_MHARTID + * + * @brief Return Hart ID Register + * + * @return mhartid value + */ +uint32_t __get_MHARTID(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mhartid" : "=r" (result) ); + return (result); +} + +/********************************************************************* + * @fn __get_SP + * + * @brief Return SP Register + * + * @return SP value + */ +uint32_t __get_SP(void) +{ + uint32_t result; + + __ASM volatile ( "mv %0," "sp" : "=r"(result) : ); + return (result); +} + diff --git a/CH5xx_ble_firmware_library/RVMSIS/core_riscv.h b/CH5xx_ble_firmware_library/RVMSIS/core_riscv.h new file mode 100644 index 0000000..287c870 --- /dev/null +++ b/CH5xx_ble_firmware_library/RVMSIS/core_riscv.h @@ -0,0 +1,381 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : core_riscv.h + * Author : WCH + * Version : V1.0.1 + * Date : 2021/10/28 + * Description : CH583 RISC-V Core Peripheral Access Layer Header File + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ +#ifndef __CORE_RV3A_H__ +#define __CORE_RV3A_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* IO definitions */ +#ifdef __cplusplus + #define __I volatile /*!< defines 'read only' permissions */ +#else + #define __I volatile const /*!< defines 'read only' permissions */ +#endif +#define __O volatile /*!< defines 'write only' permissions */ +#define __IO volatile /*!< defines 'read / write' permissions */ +#define RV_STATIC_INLINE static inline + +//typedef enum {SUCCESS = 0, ERROR = !SUCCESS} ErrorStatus; + +typedef enum +{ + DISABLE = 0, + ENABLE = !DISABLE +} FunctionalState; +typedef enum +{ + RESET = 0, + SET = !RESET +} FlagStatus, ITStatus; + +/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */ +typedef struct +{ + __I uint32_t ISR[8]; // 0 + __I uint32_t IPR[8]; // 20H + __IO uint32_t ITHRESDR; // 40H + uint8_t RESERVED[4]; // 44H + __O uint32_t CFGR; // 48H + __I uint32_t GISR; // 4CH + __IO uint8_t IDCFGR[4]; // 50H + uint8_t RESERVED0[0x0C]; // 54H + __IO uint32_t FIADDRR[4]; // 60H + uint8_t RESERVED1[0x90]; // 70H + __O uint32_t IENR[8]; // 100H + uint8_t RESERVED2[0x60]; // 120H + __O uint32_t IRER[8]; // 180H + uint8_t RESERVED3[0x60]; // 1A0H + __O uint32_t IPSR[8]; // 200H + uint8_t RESERVED4[0x60]; // 220H + __O uint32_t IPRR[8]; // 280H + uint8_t RESERVED5[0x60]; // 2A0H + __IO uint32_t IACTR[8]; // 300H + uint8_t RESERVED6[0xE0]; // 320H + __IO uint8_t IPRIOR[256]; // 400H + uint8_t RESERVED7[0x810]; // 500H + __IO uint32_t SCTLR; // D10H +} PFIC_Type; + +/* memory mapped structure for SysTick */ +typedef struct +{ + __IO uint32_t CTLR; + __IO uint32_t SR; + __IO uint64_t CNT; + __IO uint64_t CMP; +} SysTick_Type; + +#define PFIC ((PFIC_Type *)0xE000E000) +#define SysTick ((SysTick_Type *)0xE000F000) + +#define PFIC_KEY1 ((uint32_t)0xFA050000) +#define PFIC_KEY2 ((uint32_t)0xBCAF0000) +#define PFIC_KEY3 ((uint32_t)0xBEEF0000) + +/* ########################## define #################################### */ +#define __nop() __asm__ volatile("nop") + +#define read_csr(reg) ({unsigned long __tmp; \ + __asm__ volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define write_csr(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + __asm__ volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + __asm__ volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define PFIC_EnableAllIRQ() write_csr(0x800, 0x88) +#define PFIC_DisableAllIRQ() write_csr(0x800, 0x80) +/* ########################## PFIC functions #################################### */ + +/******************************************************************************* + * @fn PFIC_EnableIRQ + * + * @brief Enable Interrupt + * + * @param IRQn - Interrupt Numbers + */ +RV_STATIC_INLINE void PFIC_EnableIRQ(IRQn_Type IRQn) +{ + PFIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn)&0x1F)); +} + +/******************************************************************************* + * @fn PFIC_DisableIRQ + * + * @brief Disable Interrupt + * + * @param IRQn - Interrupt Numbers + */ +RV_STATIC_INLINE void PFIC_DisableIRQ(IRQn_Type IRQn) +{ + PFIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn)&0x1F)); + __nop(); + __nop(); +} + +/******************************************************************************* + * @fn PFIC_GetStatusIRQ + * + * @brief Get Interrupt Enable State + * + * @param IRQn - Interrupt Numbers + * + * @return 1: Interrupt Enable + * 0: Interrupt Disable + */ +RV_STATIC_INLINE uint32_t PFIC_GetStatusIRQ(IRQn_Type IRQn) +{ + return ((uint32_t)((PFIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn)&0x1F))) ? 1 : 0)); +} + +/******************************************************************************* + * @fn PFIC_GetPendingIRQ + * + * @brief Get Interrupt Pending State + * + * @param IRQn - Interrupt Numbers + * + * @return 1: Interrupt Pending Enable + * 0: Interrupt Pending Disable + */ +RV_STATIC_INLINE uint32_t PFIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return ((uint32_t)((PFIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn)&0x1F))) ? 1 : 0)); +} + +/******************************************************************************* + * @fn PFIC_SetPendingIRQ + * + * @brief Set Interrupt Pending + * + * @param IRQn - Interrupt Numbers + */ +RV_STATIC_INLINE void PFIC_SetPendingIRQ(IRQn_Type IRQn) +{ + PFIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn)&0x1F)); +} + +/******************************************************************************* + * @fn PFIC_ClearPendingIRQ + * + * @brief Clear Interrupt Pending + * + * @param IRQn - Interrupt Numbers + */ +RV_STATIC_INLINE void PFIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + PFIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn)&0x1F)); +} + +/******************************************************************************* + * @fn PFIC_GetActive + * + * @brief Get Interrupt Active State + * + * @param IRQn - Interrupt Numbers + * + * @return 1: Interrupt Active + * 0: Interrupt No Active. + */ +RV_STATIC_INLINE uint32_t PFIC_GetActive(IRQn_Type IRQn) +{ + return ((uint32_t)((PFIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn)&0x1F))) ? 1 : 0)); +} + +/******************************************************************************* + * @fn PFIC_SetPriority + * + * @brief Set Interrupt Priority + * + * @param IRQn - Interrupt Numbers + * @param priority - bit7: pre-emption priority + * bit6-bit4: subpriority + */ +RV_STATIC_INLINE void PFIC_SetPriority(IRQn_Type IRQn, uint8_t priority) +{ + PFIC->IPRIOR[(uint32_t)(IRQn)] = priority; +} + +/********************************************************************* + * @fn PFIC_EnableFastINT0 + * + * @brief Set fast Interrupt 0 + * + * @param IRQn - Interrupt Numbers + * @param addr - interrupt service addr + */ +RV_STATIC_INLINE void PFIC_EnableFastINT0(IRQn_Type IRQn, uint32_t addr) +{ + PFIC->IDCFGR[0] = IRQn; + PFIC->FIADDRR[0] = (addr & 0xFFFFFFFE) | 1; +} + +/********************************************************************* + * @fn PFIC_EnableFastINT1 + * + * @brief Set fast Interrupt 1 + * + * @param IRQn - Interrupt Numbers + * @param addr - interrupt service addr + */ +RV_STATIC_INLINE void PFIC_EnableFastINT1(IRQn_Type IRQn, uint32_t addr) +{ + PFIC->IDCFGR[1] = IRQn; + PFIC->FIADDRR[1] = (addr & 0xFFFFFFFE) | 1; +} + +/********************************************************************* + * @fn PFIC_EnableFastINT2 + * + * @brief Set fast Interrupt 2 + * + * @param IRQn - Interrupt Numbers + * @param addr - interrupt service addr + */ +RV_STATIC_INLINE void PFIC_EnableFastINT2(IRQn_Type IRQn, uint32_t addr) +{ + PFIC->IDCFGR[2] = IRQn; + PFIC->FIADDRR[2] = (addr & 0xFFFFFFFE) | 1; +} + +/********************************************************************* + * @fn PFIC_EnableFastINT3 + * + * @brief Set fast Interrupt 3 + * + * @param IRQn - Interrupt Numbers + * @param addr - interrupt service addr + */ +RV_STATIC_INLINE void PFIC_EnableFastINT3(IRQn_Type IRQn, uint32_t addr) +{ + PFIC->IDCFGR[3] = IRQn; + PFIC->FIADDRR[3] = (addr & 0xFFFFFFFE) | 1; +} + +/********************************************************************* + * @fn PFIC_DisableFastINT0 + * + * @brief Disable fast Interrupt 0 + */ +RV_STATIC_INLINE void PFIC_DisableFastINT0(void) +{ + PFIC->FIADDRR[0] = PFIC->FIADDRR[0] & 0xFFFFFFFE; +} + +/********************************************************************* + * @fn PFIC_DisableFastINT1 + * + * @brief Disable fast Interrupt 1 + */ +RV_STATIC_INLINE void PFIC_DisableFastINT1(void) +{ + PFIC->FIADDRR[1] = PFIC->FIADDRR[1] & 0xFFFFFFFE; +} + +/********************************************************************* + * @fn PFIC_DisableFastINT2 + * + * @brief Disable fast Interrupt 2 + */ +RV_STATIC_INLINE void PFIC_DisableFastINT2(void) +{ + PFIC->FIADDRR[2] = PFIC->FIADDRR[2] & 0xFFFFFFFE; +} + +/********************************************************************* + * @fn PFIC_DisableFastINT3 + * + * @brief Disable fast Interrupt 3 + */ +RV_STATIC_INLINE void PFIC_DisableFastINT3(void) +{ + PFIC->FIADDRR[3] = PFIC->FIADDRR[3] & 0xFFFFFFFE; +} + +/********************************************************************* + * @fn __SEV + * + * @brief Wait for Events + */ +__attribute__((always_inline)) RV_STATIC_INLINE void __SEV(void) +{ + PFIC->SCTLR |= (1 << 3); +} + +/********************************************************************* + * @fn __WFI + * + * @brief Wait for Interrupt + */ +__attribute__((always_inline)) RV_STATIC_INLINE void __WFI(void) +{ + PFIC->SCTLR &= ~(1 << 3); // wfi + __asm__ volatile("wfi"); +} + +/********************************************************************* + * @fn __WFE + * + * @brief Wait for Events + */ +__attribute__((always_inline)) RV_STATIC_INLINE void __WFE(void) +{ + PFIC->SCTLR |= (1 << 3) | (1 << 5); // (wfi->wfe)+(__sev) + __asm__ volatile("wfi"); + PFIC->SCTLR |= (1 << 3); + __asm__ volatile("wfi"); +} + +/********************************************************************* + * @fn PFIC_SystemReset + * + * @brief Initiate a system reset request + */ +RV_STATIC_INLINE void PFIC_SystemReset(void) +{ + PFIC->CFGR = PFIC_KEY3 | (1 << 7); +} + +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFFFFFFFFFFF) +#define SysTick_CTLR_INIT (1 << 5) +#define SysTick_CTLR_MODE (1 << 4) +#define SysTick_CTLR_STRE (1 << 3) +#define SysTick_CTLR_STCLK (1 << 2) +#define SysTick_CTLR_STIE (1 << 1) +#define SysTick_CTLR_STE (1 << 0) + +#define SysTick_SR_CNTIF (1 << 0) + +RV_STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks) +{ + if((ticks - 1) > SysTick_LOAD_RELOAD_Msk) + return (1); /* Reload value impossible */ + + SysTick->CMP = ticks - 1; /* set reload register */ + PFIC_EnableIRQ(SysTick_IRQn); + SysTick->CTLR = SysTick_CTLR_INIT | + SysTick_CTLR_STRE | + SysTick_CTLR_STCLK | + SysTick_CTLR_STIE | + SysTick_CTLR_STE; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_RV3A_H__ */ diff --git a/CH5xx_ble_firmware_library/Startup/startup_CH583.S b/CH5xx_ble_firmware_library/Startup/startup_CH583.S new file mode 100644 index 0000000..b408515 --- /dev/null +++ b/CH5xx_ble_firmware_library/Startup/startup_CH583.S @@ -0,0 +1,188 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : startup_ch58x.s + * Author : WCH + * Version : V1.0.0 + * Date : 2021/02/25 + * Description : + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + + .section .init,"ax",@progbits + .global _start + .align 1 +_start: + j handle_reset + + .section .vector,"ax",@progbits + .align 1 +_vector_base: + .option norvc; + + .word 0 + .word 0 + .word NMI_Handler /* NMI Handler */ + .word HardFault_Handler /* Hard Fault Handler */ + .word 0xF5F9BDA9 + .word Ecall_M_Mode_Handler /* 5 */ + .word 0 + .word 0 + .word Ecall_U_Mode_Handler /* 8 */ + .word Break_Point_Handler /* 9 */ + .word 0 + .word 0 + .word SysTick_Handler /* SysTick Handler */ + .word 0 + .word SW_Handler /* SW Handler */ + .word 0 + /* External Interrupts */ + .word TMR0_IRQHandler /* 0: TMR0 */ + .word GPIOA_IRQHandler /* GPIOA */ + .word GPIOB_IRQHandler /* GPIOB */ + .word SPI0_IRQHandler /* SPI0 */ + .word BB_IRQHandler /* BLEB */ + .word LLE_IRQHandler /* BLEL */ + .word USB_IRQHandler /* USB */ + .word USB2_IRQHandler /* USB2 */ + .word TMR1_IRQHandler /* TMR1 */ + .word TMR2_IRQHandler /* TMR2 */ + .word UART0_IRQHandler /* UART0 */ + .word UART1_IRQHandler /* UART1 */ + .word RTC_IRQHandler /* RTC */ + .word ADC_IRQHandler /* ADC */ + .word I2C_IRQHandler /* I2C */ + .word PWMX_IRQHandler /* PWMX */ + .word TMR3_IRQHandler /* TMR3 */ + .word UART2_IRQHandler /* UART2 */ + .word UART3_IRQHandler /* UART3 */ + .word WDOG_BAT_IRQHandler /* WDOG_BAT */ + + .option rvc; + + .section .vector_handler, "ax", @progbits + .weak NMI_Handler + .weak HardFault_Handler + .weak Ecall_M_Mode_Handler + .weak Ecall_U_Mode_Handler + .weak Break_Point_Handler + .weak SysTick_Handler + .weak SW_Handler + .weak TMR0_IRQHandler + .weak GPIOA_IRQHandler + .weak GPIOB_IRQHandler + .weak SPI0_IRQHandler + .weak BB_IRQHandler + .weak LLE_IRQHandler + .weak USB_IRQHandler + .weak USB2_IRQHandler + .weak TMR1_IRQHandler + .weak TMR2_IRQHandler + .weak UART0_IRQHandler + .weak UART1_IRQHandler + .weak RTC_IRQHandler + .weak ADC_IRQHandler + .weak I2C_IRQHandler + .weak PWMX_IRQHandler + .weak TMR3_IRQHandler + .weak UART2_IRQHandler + .weak UART3_IRQHandler + .weak WDOG_BAT_IRQHandler + +NMI_Handler: 1: j 1b +HardFault_Handler: 1: j 1b +Ecall_M_Mode_Handler: 1: j 1b +Ecall_U_Mode_Handler: 1: j 1b +Break_Point_Handler: 1: j 1b +SysTick_Handler: 1: j 1b +SW_Handler: 1: j 1b +TMR0_IRQHandler: 1: j 1b +GPIOA_IRQHandler: 1: j 1b +GPIOB_IRQHandler: 1: j 1b +SPI0_IRQHandler: 1: j 1b +BB_IRQHandler: 1: j 1b +LLE_IRQHandler: 1: j 1b +USB_IRQHandler: 1: j 1b +USB2_IRQHandler: 1: j 1b +TMR1_IRQHandler: 1: j 1b +TMR2_IRQHandler: 1: j 1b +UART0_IRQHandler: 1: j 1b +UART1_IRQHandler: 1: j 1b +RTC_IRQHandler: 1: j 1b +ADC_IRQHandler: 1: j 1b +I2C_IRQHandler: 1: j 1b +PWMX_IRQHandler: 1: j 1b +TMR3_IRQHandler: 1: j 1b +UART2_IRQHandler: 1: j 1b +UART3_IRQHandler: 1: j 1b +WDOG_BAT_IRQHandler: 1: j 1b + + .section .handle_reset,"ax",@progbits + .weak handle_reset + .align 1 +handle_reset: +.option push +.option norelax + la gp, __global_pointer$ +.option pop +1: + la sp, _eusrstack + +/* Load highcode code section from flash to RAM */ +2: + la a0, _highcode_lma + la a1, _highcode_vma_start + la a2, _highcode_vma_end + bgeu a1, a2, 2f +1: + lw t0, (a0) + sw t0, (a1) + addi a0, a0, 4 + addi a1, a1, 4 + bltu a1, a2, 1b + +/* Load data section from flash to RAM */ +2: + la a0, _data_lma + la a1, _data_vma + la a2, _edata + bgeu a1, a2, 2f +1: + lw t0, (a0) + sw t0, (a1) + addi a0, a0, 4 + addi a1, a1, 4 + bltu a1, a2, 1b +2: + /* clear bss section */ + la a0, _sbss + la a1, _ebss + bgeu a0, a1, 2f +1: + sw zero, (a0) + addi a0, a0, 4 + bltu a0, a1, 1b +2: + /* ˮ߿λ & ̬Ԥλ */ + li t0, 0x1f + csrw 0xbc0, t0 + /* ǶжϡӲѹջ */ + li t0, 0x3 + csrw 0x804, t0 + + li t0, 0x88 + csrs mstatus, t0 + la t0, _vector_base + + /* ģʽΪԵַģʽ */ + ori t0, t0, 3 + csrw mtvec, t0 + + la t0, main + csrw mepc, t0 + + + mret + + diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_adc.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_adc.c new file mode 100644 index 0000000..de86726 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_adc.c @@ -0,0 +1,235 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_adc.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn ADC_DataCalib_Rough + * + * @brief ݴֵ,ȡƫֵ,ADCô˺ȡУ׼ֵ + * + * @param none + * + * @return ƫ + */ +signed short ADC_DataCalib_Rough(void) // ݴֵ,ȡƫֵ +{ + uint16_t i; + uint32_t sum = 0; + uint8_t ch = 0; // ͨ + + ch = R8_ADC_CHANNEL; + + ADC_ChannelCfg(1); // ADCУ׼ͨѡͨ1 + R8_ADC_CFG |= RB_ADC_OFS_TEST; // ģʽ + R8_ADC_CONVERT = RB_ADC_START; + while(R8_ADC_CONVERT & RB_ADC_START); + for(i = 0; i < 16; i++) + { + R8_ADC_CONVERT = RB_ADC_START; + while(R8_ADC_CONVERT & RB_ADC_START); + sum += (~R16_ADC_DATA) & RB_ADC_DATA; + } + sum = (sum + 8) >> 4; + R8_ADC_CFG &= ~RB_ADC_OFS_TEST; // رղģʽ + + R8_ADC_CHANNEL = ch; + + return (2048 - sum); +} + +/********************************************************************* + * @fn ADC_ExtSingleChSampInit + * + * @brief ⲿźŵͨʼ + * + * @param sp - refer to ADC_SampClkTypeDef + * @param ga - refer to ADC_SignalPGATypeDef + * + * @return none + */ +void ADC_ExtSingleChSampInit(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga) +{ + R8_TKEY_CFG &= ~RB_TKEY_PWR_ON; + R8_ADC_CFG = RB_ADC_POWER_ON | RB_ADC_BUF_EN | (sp << 6) | (ga << 4); +} + +/********************************************************************* + * @fn ADC_ExtDiffChSampInit + * + * @brief ⲿźŲͨʼ + * + * @param sp - refer to ADC_SampClkTypeDef + * @param ga - refer to ADC_SignalPGATypeDef + * + * @return none + */ +void ADC_ExtDiffChSampInit(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga) +{ + R8_TKEY_CFG &= ~RB_TKEY_PWR_ON; + R8_ADC_CFG = RB_ADC_POWER_ON | RB_ADC_DIFF_EN | (sp << 6) | (ga << 4); +} + +/********************************************************************* + * @fn ADC_InterTSSampInit + * + * @brief ¶ȴʼ + * + * @param none + * + * @return none + */ +void ADC_InterTSSampInit(void) +{ + R8_TKEY_CFG &= ~RB_TKEY_PWR_ON; + R8_TEM_SENSOR = RB_TEM_SEN_PWR_ON; + R8_ADC_CHANNEL = CH_INTE_VTEMP; + R8_ADC_CFG = RB_ADC_POWER_ON | RB_ADC_DIFF_EN | (3 << 4); +} + +/********************************************************************* + * @fn ADC_InterBATSampInit + * + * @brief õصѹʼ + * + * @param none + * + * @return none + */ +void ADC_InterBATSampInit(void) +{ + R8_TKEY_CFG &= ~RB_TKEY_PWR_ON; + R8_ADC_CHANNEL = CH_INTE_VBAT; + R8_ADC_CFG = RB_ADC_POWER_ON | RB_ADC_BUF_EN | (0 << 4); // ʹ-12dBģʽ +} + +/********************************************************************* + * @fn TouchKey_ChSampInit + * + * @brief ͨʼ + * + * @param none + * + * @return none + */ +void TouchKey_ChSampInit(void) +{ + R8_ADC_CFG = RB_ADC_POWER_ON | RB_ADC_BUF_EN | (2 << 4); + R8_TKEY_CFG |= RB_TKEY_PWR_ON; +} + +/********************************************************************* + * @fn ADC_ExcutSingleConver + * + * @brief ADCִеת + * + * @param none + * + * @return ADCת + */ +uint16_t ADC_ExcutSingleConver(void) +{ + R8_ADC_CONVERT = RB_ADC_START; + while(R8_ADC_CONVERT & RB_ADC_START); + + return (R16_ADC_DATA & RB_ADC_DATA); +} + +/********************************************************************* + * @fn TouchKey_ExcutSingleConver + * + * @brief TouchKeyת + * + * @param charg - Touchkeyʱ,5bitsЧ, t=charg*Tadc + * @param disch - Touchkeyŵʱ,3bitsЧ, t=disch*Tadc + * + * @return ǰTouchKeyЧ + */ +uint16_t TouchKey_ExcutSingleConver(uint8_t charg, uint8_t disch) +{ + R8_TKEY_COUNT = (disch << 5) | (charg & 0x1f); + R8_TKEY_CONVERT = RB_TKEY_START; + while(R8_TKEY_CONVERT & RB_TKEY_START); + return (R16_ADC_DATA & RB_ADC_DATA); +} + +/********************************************************************* + * @fn ADC_AutoConverCycle + * + * @brief ADC + * + * @param cycle - ڼ㷽Ϊ(256-cycle)*16*Tsys + * + * @return none + */ +void ADC_AutoConverCycle(uint8_t cycle) +{ + R8_ADC_AUTO_CYCLE = cycle; +} + +/********************************************************************* + * @fn ADC_DMACfg + * + * @brief DMA + * + * @param s - ǷDMA + * @param startAddr - DMA ʼַ + * @param endAddr - DMA ַ + * @param m - DMAģʽ + * + * @return none + */ +void ADC_DMACfg(uint8_t s, uint16_t startAddr, uint16_t endAddr, ADC_DMAModeTypeDef m) +{ + if(s == DISABLE) + { + R8_ADC_CTRL_DMA &= ~(RB_ADC_DMA_ENABLE | RB_ADC_IE_DMA_END); + } + else + { + R16_ADC_DMA_BEG = startAddr; + R16_ADC_DMA_END = endAddr; + if(m) + { + R8_ADC_CTRL_DMA |= RB_ADC_DMA_LOOP | RB_ADC_IE_DMA_END | RB_ADC_DMA_ENABLE; + } + else + { + R8_ADC_CTRL_DMA &= ~RB_ADC_DMA_LOOP; + R8_ADC_CTRL_DMA |= RB_ADC_IE_DMA_END | RB_ADC_DMA_ENABLE; + } + } +} + +/********************************************************************* + * @fn adc_to_temperature_celsius + * + * @brief Convert ADC value to temperature(Celsius) + * + * @param adc_val - adc value + * + * @return temperature (Celsius) + */ + +int adc_to_temperature_celsius(uint16_t adc_val) +{ + uint32_t C25 = 0; + int temp; + + C25 = (*((PUINT32)ROM_CFG_TMP_25C)); + + /* current temperature = standard temperature + (adc deviation * adc linearity coefficient) */ + temp = (((C25 >> 16) & 0xFFFF) ? ((C25 >> 16) & 0xFFFF) : 25) + \ + (adc_val - ((int)(C25 & 0xFFFF))) * 10 / 27; + + return (temp); +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c new file mode 100644 index 0000000..a1d345f --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c @@ -0,0 +1,477 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_clk.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn LClk32K_Select + * + * @brief 32K ƵʱԴ + * + * @param hc - ѡ32Kʹڲⲿ + * + * @return none + */ +void LClk32K_Select(LClk32KTypeDef hc) +{ + uint8_t cfg = R8_CK32K_CONFIG; + + if(hc == Clk32K_LSI) + { + cfg &= ~RB_CLK_OSC32K_XT; + } + else + { + cfg |= RB_CLK_OSC32K_XT; + } + + sys_safe_access_enable(); + R8_CK32K_CONFIG = cfg; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn HSECFG_Current + * + * @brief HSE ƫõ + * + * @param c - 75%,100%,125%,150% + * + * @return none + */ +void HSECFG_Current(HSECurrentTypeDef c) +{ + uint8_t x32M_c; + + x32M_c = R8_XT32M_TUNE; + x32M_c = (x32M_c & 0xfc) | (c & 0x03); + + sys_safe_access_enable(); + R8_XT32M_TUNE = x32M_c; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn HSECFG_Capacitance + * + * @brief HSE ص + * + * @param c - refer to HSECapTypeDef + * + * @return none + */ +void HSECFG_Capacitance(HSECapTypeDef c) +{ + uint8_t x32M_c; + + x32M_c = R8_XT32M_TUNE; + x32M_c = (x32M_c & 0x8f) | (c << 4); + + sys_safe_access_enable(); + R8_XT32M_TUNE = x32M_c; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn LSECFG_Current + * + * @brief LSE ƫõ + * + * @param c - 70%,100%,140%,200% + * + * @return none + */ +void LSECFG_Current(LSECurrentTypeDef c) +{ + uint8_t x32K_c; + + x32K_c = R8_XT32K_TUNE; + x32K_c = (x32K_c & 0xfc) | (c & 0x03); + + sys_safe_access_enable(); + R8_XT32K_TUNE = x32K_c; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn LSECFG_Capacitance + * + * @brief LSE ص + * + * @param c - refer to LSECapTypeDef + * + * @return none + */ +void LSECFG_Capacitance(LSECapTypeDef c) +{ + uint8_t x32K_c; + + x32K_c = R8_XT32K_TUNE; + x32K_c = (x32K_c & 0x0f) | (c << 4); + + sys_safe_access_enable(); + R8_XT32K_TUNE = x32K_c; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn Calibration_LSI + * + * @brief У׼ڲ32Kʱ + * + * @param cali_Lv - У׼ȼѡ Level_32 - ʱ 1.2ms 1000ppm (32M Ƶ) 1100ppm (60M Ƶ) + * Level_64 - ʱ 2.2ms 800ppm (32M Ƶ) 1000ppm (60M Ƶ) + * Level_128 - ʱ 4.2ms 600ppm (32M Ƶ) 800ppm (60M Ƶ) + * + * @return none + */ +void Calibration_LSI(Cali_LevelTypeDef cali_Lv) +{ + UINT32 i; + INT32 cnt_offset; + UINT8 retry = 0; + INT32 freq_sys; + + freq_sys = GetSysClock(); + + sys_safe_access_enable(); + R8_CK32K_CONFIG |= RB_CLK_OSC32K_FILT; + R8_CK32K_CONFIG &= ~RB_CLK_OSC32K_FILT; + sys_safe_access_enable(); + R8_XT32K_TUNE &= ~3; + R8_XT32K_TUNE |= 1; + + // ֵ + sys_safe_access_enable(); + R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_TOTAL; + R8_OSC_CAL_CTRL |= 1; + sys_safe_access_enable(); + R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN; + R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR; + while( (R8_OSC_CAL_CTRL &RB_OSC_CNT_EN) == 0 ) + { + sys_safe_access_enable(); + R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN; + } + while(1) + { + while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT)); + i = R16_OSC_CAL_CNT; // ڶ + while(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT); + R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR; + while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT)); + i = R16_OSC_CAL_CNT; // ʵʱУ׼ֵ + cnt_offset = (i & 0x3FFF) + R8_OSC_CAL_OV_CNT * 0x3FFF - 2000 * (freq_sys / 1000) / CAB_LSIFQ; + if(((cnt_offset > -37 * (freq_sys / 1000) / CAB_LSIFQ) && (cnt_offset < 37 * (freq_sys / 1000) / CAB_LSIFQ)) || retry > 2) + { + if(retry) + break; + } + retry++; + cnt_offset = (cnt_offset > 0) ? (((cnt_offset * 2) / (74 * (freq_sys/1000) / 60000)) + 1) / 2 : (((cnt_offset * 2) / (74 * (freq_sys/1000) / 60000 )) - 1) / 2; + sys_safe_access_enable(); + R16_INT32K_TUNE += cnt_offset; + } + + // ϸ + // ϸ󣬶2βֵΪжһΣֻһ + while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT)); + i = R16_OSC_CAL_CNT; // ڶ + R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR; + sys_safe_access_enable(); + R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_TOTAL; + R8_OSC_CAL_CTRL |= cali_Lv; + while( (R8_OSC_CAL_CTRL&0x07) != cali_Lv ) + { + sys_safe_access_enable(); + R8_OSC_CAL_CTRL |= cali_Lv; + } + while(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT); + while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT)); + i = R16_OSC_CAL_CNT; // ʵʱУ׼ֵ + + cnt_offset = (i & 0x3FFF) + R8_OSC_CAL_OV_CNT * 0x3FFF - 4000 * (1 << cali_Lv) * (freq_sys / 1000000) / 256 * 1000/(CAB_LSIFQ/256) ; + cnt_offset = (cnt_offset > 0) ? ((((cnt_offset * 2*(100 )) / (1366 * ((1 << cali_Lv)/8) * (freq_sys/1000) / 60000)) + 1) / 2)<<5 : ((((cnt_offset * 2*(100)) / (1366 * ((1 << cali_Lv)/8) * (freq_sys/1000) / 60000)) - 1) / 2)<<5; + sys_safe_access_enable(); + R16_INT32K_TUNE += cnt_offset; + R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_EN; +} + +/********************************************************************* + * @fn RTCInitTime + * + * @brief RTCʱӳʼǰʱ + * + * @param y - ꣬MAX_Y = BEGYEAR + 44 + * @param mon - £MAX_MON = 12 + * @param d - գMAX_D = 31 + * @param h - СʱMAX_H = 23 + * @param m - ÷ӣMAX_M = 59 + * @param s - 룬MAX_S = 59 + * + * @return none + */ +void RTC_InitTime(uint16_t y, uint16_t mon, uint16_t d, uint16_t h, uint16_t m, uint16_t s) +{ + uint32_t t; + uint16_t year, month, day, sec2, t32k; + volatile uint8_t clk_pin; + + year = y; + month = mon; + day = 0; + while(year > BEGYEAR) + { + day += YearLength(year - 1); + year--; + } + while(month > 1) + { + day += monthLength(IsLeapYear(y), month - 2); + month--; + } + + day += d - 1; + sec2 = (h % 24) * 1800 + m * 30 + s / 2; + t32k = (s & 1) ? (0x8000) : (0); + t = sec2; + t = t << 16 | t32k; + + do + { + clk_pin = (R8_CK32K_CONFIG & RB_32K_CLK_PIN); + } while(clk_pin != (R8_CK32K_CONFIG & RB_32K_CLK_PIN)); + if(!clk_pin) + { + while(!clk_pin) + { + do + { + clk_pin = (R8_CK32K_CONFIG & RB_32K_CLK_PIN); + } while(clk_pin != (R8_CK32K_CONFIG & RB_32K_CLK_PIN)); + } + } + + sys_safe_access_enable(); + R32_RTC_TRIG = day; + R8_RTC_MODE_CTRL |= RB_RTC_LOAD_HI; + while((R32_RTC_TRIG & 0x3FFF) != (R32_RTC_CNT_DAY & 0x3FFF)); + sys_safe_access_enable(); + R32_RTC_TRIG = t; + R8_RTC_MODE_CTRL |= RB_RTC_LOAD_LO; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn RTC_GetTime + * + * @brief ȡǰʱ + * + * @param py - ȡ꣬MAX_Y = BEGYEAR + 44 + * @param pmon - ȡ£MAX_MON = 12 + * @param pd - ȡգMAX_D = 31 + * @param ph - ȡСʱMAX_H = 23 + * @param pm - ȡķӣMAX_M = 59 + * @param ps - ȡ룬MAX_S = 59 + * + * @return none + */ +void RTC_GetTime(uint16_t *py, uint16_t *pmon, uint16_t *pd, uint16_t *ph, uint16_t *pm, uint16_t *ps) +{ + uint32_t t; + uint16_t day, sec2, t32k; + + day = R32_RTC_CNT_DAY & 0x3FFF; + sec2 = R16_RTC_CNT_2S; + t32k = R16_RTC_CNT_32K; + + t = sec2 * 2 + ((t32k < 0x8000) ? 0 : 1); + + *py = BEGYEAR; + while(day >= YearLength(*py)) + { + day -= YearLength(*py); + (*py)++; + } + + *pmon = 0; + while(day >= monthLength(IsLeapYear(*py), *pmon)) + { + day -= monthLength(IsLeapYear(*py), *pmon); + (*pmon)++; + } + (*pmon)++; + *pd = day + 1; + *ph = t / 3600; + *pm = t % 3600 / 60; + *ps = t % 60; +} + +/********************************************************************* + * @fn RTC_SetCycle32k + * + * @brief LSE/LSIʱӣõǰRTC + * + * @param cyc - ڼֵMAX_CYC = 0xA8BFFFFF = 2831155199 + * + * @return none + */ +void RTC_SetCycle32k(uint32_t cyc) +{ + volatile uint8_t clk_pin; + + do + { + clk_pin = (R8_CK32K_CONFIG & RB_32K_CLK_PIN); + } while((clk_pin != (R8_CK32K_CONFIG & RB_32K_CLK_PIN)) || (!clk_pin)); + + sys_safe_access_enable(); + R32_RTC_TRIG = cyc; + R8_RTC_MODE_CTRL |= RB_RTC_LOAD_LO; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn RTC_GetCycle32k + * + * @brief LSE/LSIʱӣȡǰRTC + * + * @param none + * + * @return ǰMAX_CYC = 0xA8BFFFFF = 2831155199 + */ +uint32_t RTC_GetCycle32k(void) +{ + volatile uint32_t i; + + do + { + i = R32_RTC_CNT_32K; + } while(i != R32_RTC_CNT_32K); + + return (i); +} + +/********************************************************************* + * @fn RTC_TMRFunCfg + * + * @brief RTCʱģʽãעⶨʱ׼̶Ϊ32768Hz + * + * @param t - refer to RTC_TMRCycTypeDef + * + * @return none + */ +void RTC_TMRFunCfg(RTC_TMRCycTypeDef t) +{ + sys_safe_access_enable(); + R8_RTC_MODE_CTRL &= ~(RB_RTC_TMR_EN | RB_RTC_TMR_MODE); + sys_safe_access_enable(); + R8_RTC_MODE_CTRL |= RB_RTC_TMR_EN | (t); + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn RTC_TRIGFunCfg + * + * @brief RTCʱ䴥ģʽ + * + * @param cyc - ԵǰʱĴʱ䣬LSE/LSIʱ + * + * @return none + */ +void RTC_TRIGFunCfg(uint32_t cyc) +{ + uint32_t t; + + t = RTC_GetCycle32k() + cyc; + if(t > 0xA8C00000) + { + t -= 0xA8C00000; + } + + sys_safe_access_enable(); + R32_RTC_TRIG = t; + R8_RTC_MODE_CTRL |= RB_RTC_TRIG_EN; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn RTC_ModeFunDisable + * + * @brief RTC ģʽܹر + * + * @param m - Ҫرյĵǰģʽ + * + * @return none + */ +void RTC_ModeFunDisable(RTC_MODETypeDef m) +{ + uint8_t i = 0; + + if(m == RTC_TRIG_MODE) + { + i |= RB_RTC_TRIG_EN; + } + else if(m == RTC_TMR_MODE) + { + i |= RB_RTC_TMR_EN; + } + + sys_safe_access_enable(); + R8_RTC_MODE_CTRL &= ~(i); + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn RTC_GetITFlag + * + * @brief ȡRTCжϱ־ + * + * @param f - refer to RTC_EVENTTypeDef + * + * @return жϱ־״̬ + */ +uint8_t RTC_GetITFlag(RTC_EVENTTypeDef f) +{ + if(f == RTC_TRIG_EVENT) + { + return (R8_RTC_FLAG_CTRL & RB_RTC_TRIG_FLAG); + } + else + { + return (R8_RTC_FLAG_CTRL & RB_RTC_TMR_FLAG); + } +} + +/********************************************************************* + * @fn RTC_ClearITFlag + * + * @brief RTCжϱ־ + * + * @param f - refer to RTC_EVENTTypeDef + * + * @return none + */ +void RTC_ClearITFlag(RTC_EVENTTypeDef f) +{ + switch(f) + { + case RTC_TRIG_EVENT: + R8_RTC_FLAG_CTRL = RB_RTC_TRIG_CLR; + break; + case RTC_TMR_EVENT: + R8_RTC_FLAG_CTRL = RB_RTC_TMR_CLR; + break; + default: + break; + } +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_flash.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_flash.c new file mode 100644 index 0000000..6c726ec --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_flash.c @@ -0,0 +1,166 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_flash.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/* RESET_EN */ +#define RESET_Enable 0x00000008 +#define RESET_Disable 0xFFFFFFF7 + +/* LOCKUP_RST_EN */ +#define UART_NO_KEY_Enable 0x00000100 +#define UART_NO_KEY_Disable 0xFFFFFEFF + +/* BOOT_PIN */ +#define BOOT_PIN_PB22 0x00000200 +#define BOOT_PIN_PB11 0xFFFFFDFF + +/* FLASH_WRProt */ +#define FLASH_WRProt 0xFFF003FF + +/********************************************************************* + * @fn FLASH_ROM_READ + * + * @brief Read Flash + * + * @param StartAddr - read address + * @param Buffer - read buffer + * @param len - read len + * + * @return none + */ +void FLASH_ROM_READ(uint32_t StartAddr, void *Buffer, uint32_t len) +{ + uint32_t i, Length = (len + 3) >> 2; + uint32_t *pCode = (uint32_t *)StartAddr; + uint32_t *pBuf = (uint32_t *)Buffer; + + for(i = 0; i < Length; i++) + { + *pBuf++ = *pCode++; + } +} + +/********************************************************************* + * @fn UserOptionByteConfig + * + * @brief Configure User Option Byte.ڵûЧЧ,ÿ¼ֻ޸һ + * (ʹøúʹùٷṩ.SļͬʱøúϵߵԽӿĬϹر) + * + * @param RESET_EN - ⲿλʹ + * @param BOOT_PIN - ENABLE-ʹĬboot-PB22,DISABLE-ʹboot-PB11 + * @param UART_NO_KEY_EN - ⰴʹ + * @param FLASHProt_Size - дС(λ4K) + * + * @return 0-Success, 1-Err + */ +uint8_t UserOptionByteConfig(FunctionalState RESET_EN, FunctionalState BOOT_PIN, FunctionalState UART_NO_KEY_EN, + uint32_t FLASHProt_Size) +{ + uint32_t s, t; + + FLASH_ROM_READ(0x14, &s, 4); + + if(s == 0xF5F9BDA9) + { + s = 0; + FLASH_EEPROM_CMD(CMD_GET_ROM_INFO, 0x7EFFC, &s, 4); + s &= 0xFF; + + if(RESET_EN == ENABLE) + s |= RESET_Enable; + else + s &= RESET_Disable; + + /* bit[7:0]-bit[31-24] */ + s |= ((~(s << 24)) & 0xFF000000); //8λ Ϣȡ + + if(BOOT_PIN == ENABLE) + s |= BOOT_PIN_PB22; + if(UART_NO_KEY_EN == ENABLE) + s |= UART_NO_KEY_Enable; + + /* bit[23-10] */ + s &= 0xFF0003FF; + s |= ((FLASHProt_Size << 10) | (5 << 20)) & 0x00FFFC00; + + /*Write user option byte*/ + FLASH_ROM_WRITE(0x14, &s, 4); + + /* Verify user option byte */ + FLASH_ROM_READ(0x14, &t, 4); + + if(s == t) + return 0; + else + return 1; + } + + return 1; +} + +/********************************************************************* + * @fn UserOptionByteClose_SWD + * + * @brief ߵԽӿڣֲֵ.ڵûЧЧ,ÿ¼ֻ޸һ + * (ʹøúʹùٷṩ.SļͬʱøúϵߵԽӿĬϹر) + * + * @return 0-Success, 1-Err + */ +uint8_t UserOptionByteClose_SWD(void) +{ + uint32_t s, t; + + FLASH_ROM_READ(0x14, &s, 4); + + if(s == 0xF5F9BDA9) + { + FLASH_EEPROM_CMD(CMD_GET_ROM_INFO, 0x7EFFC, &s, 4); + + s &= ~((1 << 4) | (1 << 7)); //õԹܣ SPIдFLASH + + /* bit[7:0]-bit[31-24] */ + s &= 0x00FFFFFF; + s |= ((~(s << 24)) & 0xFF000000); //8λ Ϣȡ + + /*Write user option byte*/ + FLASH_ROM_WRITE(0x14, &s, 4); + + /* Verify user option byte */ + FLASH_ROM_READ(0x14, &t, 4); + + if(s == t) + return 0; + else + return 1; + } + + return 1; +} + +/********************************************************************* + * @fn UserOptionByte_Active + * + * @brief ûЧִкԶλ + * + * @return 0-Success, 1-Err + */ +void UserOptionByte_Active(void) +{ + FLASH_ROM_SW_RESET(); + sys_safe_access_enable(); + R16_INT32K_TUNE = 0xFFFF; + sys_safe_access_enable(); + R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET; + sys_safe_access_disable(); + while(1); +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_gpio.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_gpio.c new file mode 100644 index 0000000..f0469b2 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_gpio.c @@ -0,0 +1,263 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_gpio.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn GPIOA_ModeCfg + * + * @brief GPIOA˿ģʽ + * + * @param pin - PA0-PA15 + * @param mode - + * + * @return none + */ +void GPIOA_ModeCfg(uint32_t pin, GPIOModeTypeDef mode) +{ + switch(mode) + { + case GPIO_ModeIN_Floating: + R32_PA_PD_DRV &= ~pin; + R32_PA_PU &= ~pin; + R32_PA_DIR &= ~pin; + break; + + case GPIO_ModeIN_PU: + R32_PA_PD_DRV &= ~pin; + R32_PA_PU |= pin; + R32_PA_DIR &= ~pin; + break; + + case GPIO_ModeIN_PD: + R32_PA_PD_DRV |= pin; + R32_PA_PU &= ~pin; + R32_PA_DIR &= ~pin; + break; + + case GPIO_ModeOut_PP_5mA: + R32_PA_PD_DRV &= ~pin; + R32_PA_DIR |= pin; + break; + + case GPIO_ModeOut_PP_20mA: + R32_PA_PD_DRV |= pin; + R32_PA_DIR |= pin; + break; + + default: + break; + } +} + +/********************************************************************* + * @fn GPIOB_ModeCfg + * + * @brief GPIOB˿ģʽ + * + * @param pin - PB0-PB23 + * @param mode - + * + * @return none + */ +void GPIOB_ModeCfg(uint32_t pin, GPIOModeTypeDef mode) +{ + switch(mode) + { + case GPIO_ModeIN_Floating: + R32_PB_PD_DRV &= ~pin; + R32_PB_PU &= ~pin; + R32_PB_DIR &= ~pin; + break; + + case GPIO_ModeIN_PU: + R32_PB_PD_DRV &= ~pin; + R32_PB_PU |= pin; + R32_PB_DIR &= ~pin; + break; + + case GPIO_ModeIN_PD: + R32_PB_PD_DRV |= pin; + R32_PB_PU &= ~pin; + R32_PB_DIR &= ~pin; + break; + + case GPIO_ModeOut_PP_5mA: + R32_PB_PD_DRV &= ~pin; + R32_PB_DIR |= pin; + break; + + case GPIO_ModeOut_PP_20mA: + R32_PB_PD_DRV |= pin; + R32_PB_DIR |= pin; + break; + + default: + break; + } +} + +/********************************************************************* + * @fn GPIOA_ITModeCfg + * + * @brief GPIOAжģʽ + * + * @param pin - PA0-PA15 + * @param mode - + * + * @return none + */ +void GPIOA_ITModeCfg(uint32_t pin, GPIOITModeTpDef mode) +{ + switch(mode) + { + case GPIO_ITMode_LowLevel: // ͵ƽ + R16_PA_INT_MODE &= ~pin; + R32_PA_CLR |= pin; + break; + + case GPIO_ITMode_HighLevel: // ߵƽ + R16_PA_INT_MODE &= ~pin; + R32_PA_OUT |= pin; + break; + + case GPIO_ITMode_FallEdge: // ½ش + R16_PA_INT_MODE |= pin; + R32_PA_CLR |= pin; + break; + + case GPIO_ITMode_RiseEdge: // ش + R16_PA_INT_MODE |= pin; + R32_PA_OUT |= pin; + break; + + default: + break; + } + R16_PA_INT_IF = pin; + R16_PA_INT_EN |= pin; +} + +/********************************************************************* + * @fn GPIOB_ITModeCfg + * + * @brief GPIOBжģʽ + * + * @param pin - PB0-PB23 + * @param mode - + * + * @return none + */ +void GPIOB_ITModeCfg(uint32_t pin, GPIOITModeTpDef mode) +{ + uint32_t Pin = pin | ((pin & (GPIO_Pin_22 | GPIO_Pin_23)) >> 14); + switch(mode) + { + case GPIO_ITMode_LowLevel: // ͵ƽ + R16_PB_INT_MODE &= ~Pin; + R32_PB_CLR |= pin; + break; + + case GPIO_ITMode_HighLevel: // ߵƽ + R16_PB_INT_MODE &= ~Pin; + R32_PB_OUT |= pin; + break; + + case GPIO_ITMode_FallEdge: // ½ش + R16_PB_INT_MODE |= Pin; + R32_PB_CLR |= pin; + break; + + case GPIO_ITMode_RiseEdge: // ش + R16_PB_INT_MODE |= Pin; + R32_PB_OUT |= pin; + break; + + default: + break; + } + R16_PB_INT_IF = Pin; + R16_PB_INT_EN |= Pin; +} + +/********************************************************************* + * @fn GPIOPinRemap + * + * @brief 蹦ӳ + * + * @param s - Ƿʹӳ + * @param perph - RB_RF_ANT_SW_EN - RF antenna switch control output on PB16/PB17/PB18/PB19/PB20/PB21 + * RB_PIN_U0_INV - RXD0/RXD0_/TXD0/TXD0_ invert input/output + * RB_PIN_INTX - INTX: INT24/INT25 PB8/PB9 -> INT24_/INT25_ PB22/PB23 + * RB_PIN_MODEM - MODEM: PB1/PB5 -> PB14/PB15 + * RB_PIN_I2C - I2C: PB13/PB12 -> PB21/PB20 + * RB_PIN_PWMX - PWMX: PA12/PA13/PB4/PB6/PB7 -> PA6/PA7/PB1/PB2/PB3 + * RB_PIN_SPI0 - SPI0: PA12/PA13/PA14/PA15 -> PB12/PB13/PB14/PB15 + * RB_PIN_UART3 - UART3: PA4/PA5 -> PB20/PB21 + * RB_PIN_UART2 - UART2: PA6/PA7 -> PB22/PB23 + * RB_PIN_UART1 - UART1: PA8/PA9 -> PB12/PB13 + * RB_PIN_UART0 - UART0: PB4/PB7 -> PA15/PA14 + * RB_PIN_TMR3 - TMR2: PA9 -> PB23 + * RB_PIN_TMR2 - TMR2: PA11 -> PB11 + * RB_PIN_TMR1 - TMR1: PA10 -> PB10 + * RB_PIN_TMR0 - TMR0: PA9 -> PB23 + * + * @return none + */ +void GPIOPinRemap(FunctionalState s, uint16_t perph) +{ + if(s) + { + R16_PIN_ALTERNATE |= perph; + } + else + { + R16_PIN_ALTERNATE &= ~perph; + } +} + +/********************************************************************* + * @fn GPIOAGPPCfg + * + * @brief ģGPIOŹܿ + * + * @param s - ENABLE - ģ蹦ܣرֹ + * DISABLE - ֹܣرģ蹦 + * @param perph - RB_PIN_ADC8_9_IE - ADC/TKEY 9/8ͨ + * RB_PIN_ADC6_7_IE - ADC/TKEY 7/6ͨ + * RB_PIN_ADC10_IE - ADC/TKEY 10ͨ + * RB_PIN_ADC11_IE - ADC/TKEY 11 ͨ + * RB_PIN_USB2_DP_PU - USB2 U2D+ڲ + * RB_PIN_USB2_IE - USB2 + * RB_PIN_USB_DP_PU - USB UD+ڲ + * RB_PIN_USB_IE - USB + * RB_PIN_ADC0_IE - ADC/TKEY 0 ͨ + * RB_PIN_ADC1_IE - ADC/TKEY 1 ͨ + * RB_PIN_ADC12_IE - ADC/TKEY 12 ͨ + * RB_PIN_ADC13_IE - ADC/TKEY 13 ͨ + * RB_PIN_XT32K_IE - 32KHzLSE + * RB_PIN_ADC2_3_IE - ADC/TKEY 2/3 ͨ + * RB_PIN_ADC4_5_IE - ADC/TKEY 4/5 ͨ + * + * @return none + */ +void GPIOAGPPCfg(FunctionalState s, uint16_t perph) +{ + if(s) + { + R16_PIN_ANALOG_IE |= perph; + } + else + { + R16_PIN_ANALOG_IE &= ~perph; + } +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_i2c.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_i2c.c new file mode 100644 index 0000000..48d3355 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_i2c.c @@ -0,0 +1,672 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_i2c.c + * Author : WCH + * Version : V1.0 + * Date : 2021/03/15 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn I2C_Init + * + * @brief Initializes the I2Cx peripheral according to the specified + * parameters in the I2C_InitStruct. + * + * @param I2C_Mode - refer to I2C_ModeTypeDef + * @param I2C_ClockSpeed - Specifies the clock frequency(Hz). + * This parameter must be set to a value lower than 400kHz + * @param I2C_DutyCycle - Specifies the I2C fast mode duty cycle.refer to I2C_DutyTypeDef + * @param I2C_Ack - Enables or disables the acknowledgement.refer to I2C_AckTypeDef + * @param I2C_AckAddr - Specifies if 7-bit or 10-bit address is acknowledged.refer to I2C_AckAddrTypeDef + * @param I2C_OwnAddress1 - Specifies the first device own address. + * This parameter can be a 7-bit or 10-bit address. + * + * @return none + */ +void I2C_Init(I2C_ModeTypeDef I2C_Mode, UINT32 I2C_ClockSpeed, I2C_DutyTypeDef I2C_DutyCycle, + I2C_AckTypeDef I2C_Ack, I2C_AckAddrTypeDef I2C_AckAddr, UINT16 I2C_OwnAddress1) +{ + uint32_t sysClock; + uint16_t tmpreg; + + I2C_SoftwareResetCmd(ENABLE); + I2C_SoftwareResetCmd(DISABLE); + + sysClock = GetSysClock(); + + R16_I2C_CTRL2 &= ~RB_I2C_FREQ; + R16_I2C_CTRL2 |= (sysClock / 1000000); + + R16_I2C_CTRL1 &= ~RB_I2C_PE; + + if(I2C_ClockSpeed <= 100000) + { + tmpreg = (sysClock / (I2C_ClockSpeed << 1)) & RB_I2C_CCR; + + if(tmpreg < 0x04) + tmpreg = 0x04; + + R16_I2C_RTR = (((sysClock / 1000000) + 1) > 0x3F) ? 0x3F : ((sysClock / 1000000) + 1); + } + else + { + if(I2C_DutyCycle == I2C_DutyCycle_2) + { + tmpreg = (sysClock / (I2C_ClockSpeed * 3)) & RB_I2C_CCR; + } + else + { + tmpreg = (sysClock / (I2C_ClockSpeed * 25)) & RB_I2C_CCR; + tmpreg |= I2C_DutyCycle_16_9; + } + + if(tmpreg == 0) + { + tmpreg |= (uint16_t)0x0001; + } + + tmpreg |= RB_I2C_F_S; + R16_I2C_RTR = (uint16_t)((((sysClock / 1000000) * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1); + } + R16_I2C_CKCFGR = tmpreg; + + R16_I2C_CTRL1 |= RB_I2C_PE; + + R16_I2C_CTRL1 &= ~(RB_I2C_SMBUS | RB_I2C_SMBTYPE | RB_I2C_ACK); + R16_I2C_CTRL1 |= I2C_Mode | I2C_Ack; + + R16_I2C_OADDR1 &= ~0xFFFF; + R16_I2C_OADDR1 |= I2C_AckAddr | I2C_OwnAddress1; +} + +/********************************************************************* + * @fn I2C_Cmd + * + * @brief Enables or disables the specified I2C peripheral. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_Cmd(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_PE; + else + R16_I2C_CTRL1 &= ~RB_I2C_PE; +} + +/********************************************************************* + * @fn I2C_GenerateSTART + * + * @brief Generates I2Cx communication START condition. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_GenerateSTART(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_START; + else + R16_I2C_CTRL1 &= ~RB_I2C_START; +} + +/********************************************************************* + * @fn I2C_GenerateSTOP + * + * @brief Generates I2Cx communication STOP condition. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_GenerateSTOP(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_STOP; + else + R16_I2C_CTRL1 &= ~RB_I2C_STOP; +} + +/********************************************************************* + * @fn I2C_AcknowledgeConfig + * + * @brief Enables or disables the specified I2C acknowledge feature. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_AcknowledgeConfig(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_ACK; + else + R16_I2C_CTRL1 &= ~RB_I2C_ACK; +} + +/********************************************************************* + * @fn I2C_OwnAddress2Config + * + * @brief Configures the specified I2C own address2. + * + * @param Address - specifies the 7bit I2C own address2. + * + * @return none + */ +void I2C_OwnAddress2Config(uint8_t Address) +{ + R16_I2C_OADDR2 &= ~RB_I2C_ADD2; + R16_I2C_OADDR2 |= (uint16_t)(Address & RB_I2C_ADD2); +} + +/********************************************************************* + * @fn I2C_DualAddressCmd + * + * @brief Enables or disables the specified I2C dual addressing mode. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_DualAddressCmd(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_OADDR2 |= RB_I2C_ENDUAL; + else + R16_I2C_OADDR2 &= ~RB_I2C_ENDUAL; +} + +/********************************************************************* + * @fn I2C_GeneralCallCmd + * + * @brief Enables or disables the specified I2C general call feature. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_GeneralCallCmd(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_ENGC; + else + R16_I2C_CTRL1 &= ~RB_I2C_ENGC; +} + +/********************************************************************* + * @fn I2C_ITConfig + * + * @brief Enables or disables the specified I2C interrupts. + * + * @param I2C_IT - specifies the I2C interrupts sources to be enabled or disabled. + * I2C_IT_BUF - Buffer interrupt mask. + * I2C_IT_EVT - Event interrupt mask. + * I2C_IT_ERR - Error interrupt mask. + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_ITConfig(I2C_ITTypeDef I2C_IT, FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL2 |= I2C_IT; + else + R16_I2C_CTRL2 &= (uint16_t)~I2C_IT; +} + +/********************************************************************* + * @fn I2C_SendData + * + * @brief Sends a data byte through the I2Cx peripheral. + * + * @param Data - Byte to be transmitted. + * + * @return none + */ +void I2C_SendData(uint8_t Data) +{ + R16_I2C_DATAR = Data; +} + +/********************************************************************* + * @fn I2C_ReceiveData + * + * @brief Returns the most recent received data by the I2Cx peripheral. + * + * @return The value of the received data. + */ +uint8_t I2C_ReceiveData(void) +{ + return (uint8_t)R16_I2C_DATAR; +} + +/********************************************************************* + * @fn I2C_Send7bitAddress + * + * @brief Transmits the address byte to select the slave device. + * + * @param Address - specifies the slave address which will be transmitted. + * @param I2C_Direction - specifies whether the I2C device will be a Transmitter or a Receiver. + * I2C_Direction_Transmitter - Transmitter mode. + * I2C_Direction_Receiver - Receiver mode. + * + * @return none + */ +void I2C_Send7bitAddress(uint8_t Address, uint8_t I2C_Direction) +{ + if(I2C_Direction != I2C_Direction_Transmitter) + Address |= OADDR1_ADD0_Set; + else + Address &= OADDR1_ADD0_Reset; + + R16_I2C_DATAR = Address; +} + +/********************************************************************* + * @fn I2C_SoftwareResetCmd + * + * @brief Enables or disables the specified I2C software reset. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_SoftwareResetCmd(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_SWRST; + else + R16_I2C_CTRL1 &= ~RB_I2C_SWRST; +} + +/********************************************************************* + * @fn I2C_NACKPositionConfig + * + * @brief Selects the specified I2C NACK position in master receiver mode. + * + * @param I2C_NACKPosition - specifies the NACK position. + * I2C_NACKPosition_Next - indicates that the next byte will be the last received byte. + * I2C_NACKPosition_Current - indicates that current byte is the last received byte. + * + * @return none + */ +void I2C_NACKPositionConfig(uint16_t I2C_NACKPosition) +{ + if(I2C_NACKPosition == I2C_NACKPosition_Next) + R16_I2C_CTRL1 |= I2C_NACKPosition_Next; + else + R16_I2C_CTRL1 &= I2C_NACKPosition_Current; +} + +/********************************************************************* + * @fn I2C_SMBusAlertConfig + * + * @brief Drives the SMBusAlert pin high or low for the specified I2C. + * + * @param I2C_SMBusAlert - specifies SMBAlert pin level. + * I2C_SMBusAlert_Low - SMBAlert pin driven low. + * I2C_SMBusAlert_High - SMBAlert pin driven high. + * + * @return none + */ +void I2C_SMBusAlertConfig(uint16_t I2C_SMBusAlert) +{ + if(I2C_SMBusAlert == I2C_SMBusAlert_Low) + R16_I2C_CTRL1 |= I2C_SMBusAlert_Low; + else + R16_I2C_CTRL1 &= I2C_SMBusAlert_High; +} + +/********************************************************************* + * @fn I2C_TransmitPEC + * + * @brief Enables or disables the specified I2C PEC transfer. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_TransmitPEC(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_PEC; + else + R16_I2C_CTRL1 &= ~RB_I2C_PEC; +} + +/********************************************************************* + * @fn I2C_PECPositionConfig + * + * @brief Selects the specified I2C PEC position. + * + * @param I2C_PECPosition - specifies the PEC position. + * I2C_PECPosition_Next - indicates that the next byte is PEC. + * I2C_PECPosition_Current - indicates that current byte is PEC. + * + * @return none + */ +void I2C_PECPositionConfig(uint16_t I2C_PECPosition) +{ + if(I2C_PECPosition == I2C_PECPosition_Next) + R16_I2C_CTRL1 |= I2C_PECPosition_Next; + else + R16_I2C_CTRL1 &= I2C_PECPosition_Current; +} + +/********************************************************************* + * @fn I2C_CalculatePEC + * + * @brief Enables or disables the PEC value calculation of the transferred bytes. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_CalculatePEC(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_ENPEC; + else + R16_I2C_CTRL1 &= ~RB_I2C_ENPEC; +} + +/********************************************************************* + * @fn I2C_GetPEC + * + * @brief Returns the PEC value for the specified I2C. + * + * @return The PEC value. + */ +uint8_t I2C_GetPEC(void) +{ + return (R16_I2C_STAR2 >> 8); +} + +/********************************************************************* + * @fn I2C_ARPCmd + * + * @brief Enables or disables the specified I2C ARP. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_ARPCmd(FunctionalState NewState) +{ + if(NewState != DISABLE) + R16_I2C_CTRL1 |= RB_I2C_EBARP; + else + R16_I2C_CTRL1 &= ~RB_I2C_EBARP; +} + +/********************************************************************* + * @fn I2C_StretchClockCmd + * + * @brief Enables or disables the specified I2C Clock stretching. + * + * @param NewState - ENABLE or DISABLE. + * + * @return none + */ +void I2C_StretchClockCmd(FunctionalState NewState) +{ + if(NewState == DISABLE) + R16_I2C_CTRL1 |= RB_I2C_NOSTRETCH; + else + R16_I2C_CTRL1 &= ~RB_I2C_NOSTRETCH; +} + +/********************************************************************* + * @fn I2C_FastModeDutyCycleConfig + * + * @brief Selects the specified I2C fast mode duty cycle. + * + * @param I2C_DutyCycle - specifies the fast mode duty cycle. + * I2C_DutyCycle_2 - I2C fast mode Tlow/Thigh = 2. + * I2C_DutyCycle_16_9 - I2C fast mode Tlow/Thigh = 16/9. + * + * @return none + */ +void I2C_FastModeDutyCycleConfig(uint16_t I2C_DutyCycle) +{ + if(I2C_DutyCycle != I2C_DutyCycle_16_9) + R16_I2C_CKCFGR &= ~I2C_DutyCycle_16_9; + else + R16_I2C_CKCFGR |= I2C_DutyCycle_16_9; +} + +/********************************************************************* + * @fn I2C_CheckEvent + * + * @brief Checks whether the last I2Cx Event is equal to the one passed as parameter. + * + * @param I2C_EVENT - specifies the event to be checked. + * I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED : EV1. + * I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED : EV1. + * I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED : EV1. + * I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED : EV1. + * I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED : EV1. + * I2C_EVENT_SLAVE_BYTE_RECEIVED : EV2. + * (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF) : EV2. + * (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL) : EV2. + * I2C_EVENT_SLAVE_BYTE_TRANSMITTED : EV3. + * (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF) : EV3. + * (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL) : EV3. + * I2C_EVENT_SLAVE_ACK_FAILURE : EV3_2. + * I2C_EVENT_SLAVE_STOP_DETECTED : EV4. + * I2C_EVENT_MASTER_MODE_SELECT : EV5. + * I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED : EV6. + * I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED : EV6. + * I2C_EVENT_MASTER_BYTE_RECEIVED : EV7. + * I2C_EVENT_MASTER_BYTE_TRANSMITTING : EV8. + * I2C_EVENT_MASTER_BYTE_TRANSMITTED : EV8_2. + * I2C_EVENT_MASTER_MODE_ADDRESS10 : EV9. + * + * @return 1 - SUCCESS or 0 - ERROR. + */ +uint8_t I2C_CheckEvent(uint32_t I2C_EVENT) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + uint8_t status = 0; + + flag1 = R16_I2C_STAR1; + flag2 = R16_I2C_STAR2; + flag2 = flag2 << 16; + + lastevent = (flag1 | flag2) & FLAG_Mask; + + if((lastevent & I2C_EVENT) == I2C_EVENT) + { + status = !0; + } + else + { + status = 0; + } + + return status; +} + +/********************************************************************* + * @fn I2C_GetLastEvent + * + * @brief Returns the last I2Cx Event. + * + * @return The last event. + */ +uint32_t I2C_GetLastEvent(void) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + + flag1 = R16_I2C_STAR1; + flag2 = R16_I2C_STAR2; + flag2 = flag2 << 16; + lastevent = (flag1 | flag2) & FLAG_Mask; + + return lastevent; +} + +/********************************************************************* + * @fn I2C_GetFlagStatus + * + * @brief Checks whether the last I2Cx Event is equal to the one passed as parameter. + * + * @param I2C_FLAG - specifies the flag to check. + * I2C_FLAG_DUALF - Dual flag (Slave mode). + * I2C_FLAG_SMBHOST - SMBus host header (Slave mode). + * I2C_FLAG_SMBDEFAULT - SMBus default header (Slave mode). + * I2C_FLAG_GENCALL - General call header flag (Slave mode). + * I2C_FLAG_TRA - Transmitter/Receiver flag. + * I2C_FLAG_BUSY - Bus busy flag. + * I2C_FLAG_MSL - Master/Slave flag. + * I2C_FLAG_SMBALERT - SMBus Alert flag. + * I2C_FLAG_TIMEOUT - Timeout or Tlow error flag. + * I2C_FLAG_PECERR - PEC error in reception flag. + * I2C_FLAG_OVR - Overrun/Underrun flag (Slave mode). + * I2C_FLAG_AF - Acknowledge failure flag. + * I2C_FLAG_ARLO - Arbitration lost flag (Master mode). + * I2C_FLAG_BERR - Bus error flag. + * I2C_FLAG_TXE - Data register empty flag (Transmitter). + * I2C_FLAG_RXNE - Data register not empty (Receiver) flag. + * I2C_FLAG_STOPF - Stop detection flag (Slave mode). + * I2C_FLAG_ADD10 - 10-bit header sent flag (Master mode). + * I2C_FLAG_BTF - Byte transfer finished flag. + * I2C_FLAG_ADDR - Address sent flag (Master mode) "ADSL" + * Address matched flag (Slave mode)"ENDA". + * I2C_FLAG_SB - Start bit flag (Master mode). + * + * @return FlagStatus - SET or RESET. + */ +FlagStatus I2C_GetFlagStatus(uint32_t I2C_FLAG) +{ + FlagStatus bitstatus = RESET; + __IO uint32_t i2creg = 0, i2cxbase = 0; + + i2cxbase = (uint32_t)BA_I2C; + i2creg = I2C_FLAG >> 28; + I2C_FLAG &= FLAG_Mask; + + if(i2creg != 0) + { + i2cxbase += 0x14; + } + else + { + I2C_FLAG = (uint32_t)(I2C_FLAG >> 16); + i2cxbase += 0x18; + } + + if(((*(__IO uint32_t *)i2cxbase) & I2C_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/********************************************************************* + * @fn I2C_ClearFlag + * + * @brief Clears the I2Cx's pending flags. + * + * @param I2C_FLAG - specifies the flag to clear. + * I2C_FLAG_SMBALERT - SMBus Alert flag. + * I2C_FLAG_TIMEOUT - Timeout or Tlow error flag. + * I2C_FLAG_PECERR - PEC error in reception flag. + * I2C_FLAG_OVR - Overrun/Underrun flag (Slave mode). + * I2C_FLAG_AF - Acknowledge failure flag. + * I2C_FLAG_ARLO - Arbitration lost flag (Master mode). + * I2C_FLAG_BERR - Bus error flag. + * + * @return none + */ +void I2C_ClearFlag(uint32_t I2C_FLAG) +{ + uint32_t flagpos = 0; + + flagpos = I2C_FLAG & FLAG_Mask; + R16_I2C_STAR1 = (uint16_t)~flagpos; +} + +/********************************************************************* + * @fn I2C_GetITStatus + * + * @brief Checks whether the specified I2C interrupt has occurred or not. + * + * @param II2C_IT - specifies the interrupt source to check. + * I2C_FLAG_SMBALERT - SMBus Alert flag. + * I2C_FLAG_TIMEOUT - Timeout or Tlow error flag. + * I2C_FLAG_PECERR - PEC error in reception flag. + * I2C_FLAG_OVR - Overrun/Underrun flag (Slave mode). + * I2C_FLAG_AF - Acknowledge failure flag. + * I2C_FLAG_ARLO - Arbitration lost flag (Master mode). + * I2C_FLAG_BERR - Bus error flag. + * I2C_FLAG_TXE - Data register empty flag (Transmitter). + * I2C_FLAG_RXNE - Data register not empty (Receiver) flag. + * I2C_FLAG_STOPF - Stop detection flag (Slave mode). + * I2C_FLAG_ADD10 - 10-bit header sent flag (Master mode). + * I2C_FLAG_BTF - Byte transfer finished flag. + * I2C_FLAG_ADDR - Address sent flag (Master mode) "ADSL" + * Address matched flag (Slave mode)"ENDA". + * I2C_FLAG_SB - Start bit flag (Master mode). + * + * @return none + */ +ITStatus I2C_GetITStatus(uint32_t I2C_IT) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + enablestatus = (uint32_t)(((I2C_IT & ITEN_Mask) >> 16) & (R16_I2C_CTRL2)); + I2C_IT &= FLAG_Mask; + + if(((R16_I2C_STAR1 & I2C_IT) != (uint32_t)RESET) && enablestatus) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/********************************************************************* + * @fn I2C_ClearITPendingBit + * + * @brief Clears the I2Cx interrupt pending bits. + * + * @param I2C_IT - specifies the interrupt pending bit to clear. + * I2C_IT_SMBALERT - SMBus Alert interrupt. + * I2C_IT_TIMEOUT - Timeout or Tlow error interrupt. + * I2C_IT_PECERR - PEC error in reception interrupt. + * I2C_IT_OVR - Overrun/Underrun interrupt (Slave mode). + * I2C_IT_AF - Acknowledge failure interrupt. + * I2C_IT_ARLO - Arbitration lost interrupt (Master mode). + * I2C_IT_BERR - Bus error interrupt. + * + * @return none + */ +void I2C_ClearITPendingBit(uint32_t I2C_IT) +{ + uint32_t flagpos = 0; + + flagpos = I2C_IT & FLAG_Mask; + R16_I2C_STAR1 = (uint16_t)~flagpos; +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwm.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwm.c new file mode 100644 index 0000000..3d885d8 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwm.c @@ -0,0 +1,123 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_pwm.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn PWMX_CycleCfg + * + * @brief PWM4-PWM11׼ʱ + * + * @param cyc - refer to PWMX_CycleTypeDef + * + * @return none + */ +void PWMX_CycleCfg(PWMX_CycleTypeDef cyc) +{ + switch(cyc) + { + case PWMX_Cycle_256: + R8_PWM_CONFIG = R8_PWM_CONFIG & 0xf0; + break; + + case PWMX_Cycle_255: + R8_PWM_CONFIG = (R8_PWM_CONFIG & 0xf0) | 0x01; + break; + + case PWMX_Cycle_128: + R8_PWM_CONFIG = (R8_PWM_CONFIG & 0xf0) | (1 << 2); + break; + + case PWMX_Cycle_127: + R8_PWM_CONFIG = (R8_PWM_CONFIG & 0xf0) | (1 << 2) | 0x01; + break; + + case PWMX_Cycle_64: + R8_PWM_CONFIG = (R8_PWM_CONFIG & 0xf0) | (2 << 2); + break; + + case PWMX_Cycle_63: + R8_PWM_CONFIG = (R8_PWM_CONFIG & 0xf0) | (2 << 2) | 0x01; + break; + + case PWMX_Cycle_32: + R8_PWM_CONFIG = (R8_PWM_CONFIG & 0xf0) | (3 << 2); + break; + + case PWMX_Cycle_31: + R8_PWM_CONFIG = (R8_PWM_CONFIG & 0xf0) | (3 << 2) | 0x01; + break; + + default: + break; + } +} + +/********************************************************************* + * @fn PWMX_ACTOUT + * + * @brief PWM4-PWM11ͨ + * + * @param ch - select channel of pwm, refer to channel of PWM define + * @param da - effective pulse width + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param s - control pwmx function, ENABLE or DISABLE + * + * @return none + */ +void PWMX_ACTOUT(uint8_t ch, uint8_t da, PWMX_PolarTypeDef pr, FunctionalState s) +{ + uint8_t i; + + if(s == DISABLE) + { + R8_PWM_OUT_EN &= ~(ch); + } + else + { + (pr) ? (R8_PWM_POLAR |= (ch)) : (R8_PWM_POLAR &= ~(ch)); + for(i = 0; i < 8; i++) + { + if((ch >> i) & 1) + { + *((volatile uint8_t *)((&R8_PWM4_DATA) + i)) = da; + } + } + R8_PWM_OUT_EN |= (ch); + } +} + +/********************************************************************* + * @fn PWMX_AlterOutCfg + * + * @brief PWM ģʽ + * + * @param ch - select group of PWM alternate output + * RB_PWM4_5_STAG_EN - PWM4 PWM5 ͨ + * RB_PWM6_7_STAG_EN - PWM6 PWM7 ͨ + * RB_PWM8_9_STAG_EN - PWM8 PWM9 ͨ + * RB_PWM10_11_STAG_EN - PWM10 PWM11 ͨ + * @param s - control pwmx function, ENABLE or DISABLE + * + * @return none + */ +void PWMX_AlterOutCfg(uint8_t ch, FunctionalState s) +{ + if(s == DISABLE) + { + R8_PWM_CONFIG &= ~(ch); + } + else + { + R8_PWM_CONFIG |= (ch); + } +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwr.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwr.c new file mode 100644 index 0000000..91f09b9 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwr.c @@ -0,0 +1,384 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_pwr.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn PWR_DCDCCfg + * + * @brief ڲDC/DCԴڽԼϵͳ + * + * @param s - ǷDCDCԴ + * + * @return none + */ +void PWR_DCDCCfg(FunctionalState s) +{ + uint16_t adj = R16_AUX_POWER_ADJ; + uint16_t plan = R16_POWER_PLAN; + + if(s == DISABLE) + { + + adj &= ~RB_DCDC_CHARGE; + plan &= ~(RB_PWR_DCDC_EN | RB_PWR_DCDC_PRE); // · DC/DC + sys_safe_access_enable(); + R16_AUX_POWER_ADJ = adj; + R16_POWER_PLAN = plan; + sys_safe_access_disable(); + } + else + { + adj |= RB_DCDC_CHARGE; + plan |= RB_PWR_DCDC_PRE; + sys_safe_access_enable(); + R16_AUX_POWER_ADJ = adj; + R16_POWER_PLAN = plan; + DelayUs(10); + sys_safe_access_enable(); + R16_POWER_PLAN |= RB_PWR_DCDC_EN; + sys_safe_access_disable(); + } +} + +/********************************************************************* + * @fn PWR_UnitModCfg + * + * @brief ɿصԪģĵԴ + * + * @param s - Ƿ򿪵Դ + * @param unit - please refer to unit of controllable power supply + * + * @return none + */ +void PWR_UnitModCfg(FunctionalState s, uint8_t unit) +{ + uint8_t pwr_ctrl = R8_HFCK_PWR_CTRL; + uint8_t ck32k_cfg = R8_CK32K_CONFIG; + + if(s == DISABLE) //ر + { + pwr_ctrl &= ~(unit & 0x1c); + ck32k_cfg &= ~(unit & 0x03); + } + else // + { + pwr_ctrl |= (unit & 0x1c); + ck32k_cfg |= (unit & 0x03); + } + + sys_safe_access_enable(); + R8_HFCK_PWR_CTRL = pwr_ctrl; + R8_CK32K_CONFIG = ck32k_cfg; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn PWR_PeriphClkCfg + * + * @brief ʱӿλ + * + * @param s - Ƿ򿪶Ӧʱ + * @param perph - please refer to Peripher CLK control bit define + * + * @return none + */ +void PWR_PeriphClkCfg(FunctionalState s, uint16_t perph) +{ + uint32_t sleep_ctrl = R32_SLEEP_CONTROL; + + if(s == DISABLE) + { + sleep_ctrl |= perph; + } + else + { + sleep_ctrl &= ~perph; + } + + sys_safe_access_enable(); + R32_SLEEP_CONTROL = sleep_ctrl; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn PWR_PeriphWakeUpCfg + * + * @brief ˯߻Դ + * + * @param s - Ƿ򿪴˯߻ѹ + * @param perph - ҪõĻԴ + * RB_SLP_USB_WAKE - USB ΪԴ + * RB_SLP_RTC_WAKE - RTC ΪԴ + * RB_SLP_GPIO_WAKE - GPIO ΪԴ + * RB_SLP_BAT_WAKE - BAT ΪԴ + * @param mode - refer to WakeUP_ModeypeDef + * + * @return none + */ +void PWR_PeriphWakeUpCfg(FunctionalState s, uint8_t perph, WakeUP_ModeypeDef mode) +{ + uint8_t m; + + if(s == DISABLE) + { + sys_safe_access_enable(); + R8_SLP_WAKE_CTRL &= ~perph; + } + else + { + switch(mode) + { + case Short_Delay: + m = 0x01; + break; + + case Long_Delay: + m = 0x00; + break; + + default: + m = 0x01; + break; + } + + sys_safe_access_enable(); + R8_SLP_WAKE_CTRL |= RB_WAKE_EV_MODE | perph; + sys_safe_access_enable(); + R8_SLP_POWER_CTRL &= ~(RB_WAKE_DLY_MOD); + sys_safe_access_enable(); + R8_SLP_POWER_CTRL |= m; + } + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn PowerMonitor + * + * @brief Դ + * + * @param s - Ƿ򿪴˹ + * @param vl - refer to VolM_LevelypeDef + * + * @return none + */ +void PowerMonitor(FunctionalState s, VolM_LevelypeDef vl) +{ + uint8_t ctrl = R8_BAT_DET_CTRL; + uint8_t cfg = R8_BAT_DET_CFG; + + if(s == DISABLE) + { + sys_safe_access_enable(); + R8_BAT_DET_CTRL = 0; + sys_safe_access_disable(); + } + else + { + if(vl & 0x80) + { + cfg = vl & 0x03; + ctrl = RB_BAT_MON_EN | ((vl >> 2) & 1); + } + else + { + + cfg = vl & 0x03; + ctrl = RB_BAT_DET_EN; + } + sys_safe_access_enable(); + R8_BAT_DET_CTRL = ctrl; + R8_BAT_DET_CFG = cfg; + sys_safe_access_disable(); + + mDelayuS(1); + sys_safe_access_enable(); + R8_BAT_DET_CTRL |= RB_BAT_LOW_IE | RB_BAT_LOWER_IE; + sys_safe_access_disable(); + } +} + +/********************************************************************* + * @fn LowPower_Idle + * + * @brief ͹-Idleģʽ + * + * @param none + * + * @return none + */ +__HIGH_CODE +void LowPower_Idle(void) +{ + FLASH_ROM_SW_RESET(); + R8_FLASH_CTRL = 0x04; //flashر + + PFIC->SCTLR &= ~(1 << 2); // sleep + __WFI(); + __nop(); + __nop(); +} + +/********************************************************************* + * @fn LowPower_Halt + * + * @brief ͹-Haltģʽ˵͹еHSI/5ʱУѺҪûԼѡϵͳʱԴ + * + * @param none + * + * @return none + */ +__HIGH_CODE +void LowPower_Halt(void) +{ + uint8_t x32Kpw, x32Mpw; + + FLASH_ROM_SW_RESET(); + R8_FLASH_CTRL = 0x04; //flashر + x32Kpw = R8_XT32K_TUNE; + x32Mpw = R8_XT32M_TUNE; + x32Mpw = (x32Mpw & 0xfc) | 0x03; // 150% + if(R16_RTC_CNT_32K > 0x3fff) + { // 500ms + x32Kpw = (x32Kpw & 0xfc) | 0x01; // LSE͵ + } + + sys_safe_access_enable(); + R8_BAT_DET_CTRL = 0; // رյѹ + sys_safe_access_enable(); + R8_XT32K_TUNE = x32Kpw; + R8_XT32M_TUNE = x32Mpw; + sys_safe_access_enable(); + R8_PLL_CONFIG |= (1 << 5); + sys_safe_access_disable(); + + PFIC->SCTLR |= (1 << 2); //deep sleep + __WFI(); + __nop(); + __nop(); + sys_safe_access_enable(); + R8_PLL_CONFIG &= ~(1 << 5); + sys_safe_access_disable(); +} + +/******************************************************************************* +* Function Name : LowPower_Sleep +* Description : ͹-Sleepģʽ + ע⵱ƵΪ80Mʱ˯߻жϲɵflashڴ룬˳˺ǰҪ30usӳ١ +* Input : rm: + RB_PWR_RAM2K - 2K retention SRAM + RB_PWR_RAM30K - 30K main SRAM + RB_PWR_EXTEND - USB BLE Ԫ򹩵 + RB_PWR_XROM - FlashROM + NULL - ϵԪϵ +* Return : None +*******************************************************************************/ +__HIGH_CODE +void LowPower_Sleep(uint8_t rm) +{ + uint8_t x32Kpw, x32Mpw; + uint16_t power_plan; + + x32Kpw = R8_XT32K_TUNE; + x32Mpw = R8_XT32M_TUNE; + x32Mpw = (x32Mpw & 0xfc) | 0x03; // 150% + if(R16_RTC_CNT_32K > 0x3fff) + { // 500ms + x32Kpw = (x32Kpw & 0xfc) | 0x01; // LSE͵ + } + + sys_safe_access_enable(); + R8_BAT_DET_CTRL = 0; // رյѹ + sys_safe_access_enable(); + R8_XT32K_TUNE = x32Kpw; + R8_XT32M_TUNE = x32Mpw; + sys_safe_access_disable(); + + PFIC->SCTLR |= (1 << 2); //deep sleep + + power_plan = R16_POWER_PLAN & (RB_PWR_DCDC_EN | RB_PWR_DCDC_PRE); + power_plan |= RB_PWR_PLAN_EN | RB_PWR_MUST_0010 | RB_PWR_CORE | rm; + __nop(); + sys_safe_access_enable(); + R8_SLP_POWER_CTRL |= RB_RAM_RET_LV; + R8_PLL_CONFIG |= (1 << 5); + R16_POWER_PLAN = power_plan; + + do{ + __WFI(); + __nop(); + __nop(); + DelayUs(70); + + uint8_t mac[6] = {0}; + + GetMACAddress(mac); + + if(mac[5] != 0xff) + break; + + }while(1); + + sys_safe_access_enable(); + R8_PLL_CONFIG &= ~(1 << 5); + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn LowPower_Shutdown + * + * @brief ͹-Shutdownģʽ˵͹еHSI/5ʱУѺҪûԼѡϵͳʱԴ + * @note עô˺DCDCǿƹرգѺֶٴδ + * + * @param rm - ģѡ + * RB_PWR_RAM2K - 2K retention SRAM + * RB_PWR_RAM16K - 16K main SRAM + * NULL - ϵԪϵ + * + * @return none + */ +__HIGH_CODE +void LowPower_Shutdown(uint8_t rm) +{ + uint8_t x32Kpw, x32Mpw; + + FLASH_ROM_SW_RESET(); + x32Kpw = R8_XT32K_TUNE; + x32Mpw = R8_XT32M_TUNE; + x32Mpw = (x32Mpw & 0xfc) | 0x03; // 150% + if(R16_RTC_CNT_32K > 0x3fff) + { // 500ms + x32Kpw = (x32Kpw & 0xfc) | 0x01; // LSE͵ + } + + sys_safe_access_enable(); + R8_BAT_DET_CTRL = 0; // رյѹ + sys_safe_access_enable(); + R8_XT32K_TUNE = x32Kpw; + R8_XT32M_TUNE = x32Mpw; + sys_safe_access_disable(); + SetSysClock(CLK_SOURCE_HSE_6_4MHz); + + PFIC->SCTLR |= (1 << 2); //deep sleep + + sys_safe_access_enable(); + R8_SLP_POWER_CTRL |= RB_RAM_RET_LV; + sys_safe_access_enable(); + R16_POWER_PLAN = RB_PWR_PLAN_EN | RB_PWR_MUST_0010 | rm; + __WFI(); + __nop(); + __nop(); + FLASH_ROM_SW_RESET(); + sys_safe_access_enable(); + R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET; + sys_safe_access_disable(); +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi0.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi0.c new file mode 100644 index 0000000..7b75bdf --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi0.c @@ -0,0 +1,368 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_SPI0.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn SPI0_MasterDefInit + * + * @brief ģʽĬϳʼģʽ0+3ȫ˫+8MHz + * + * @param none + * + * @return none + */ +void SPI0_MasterDefInit(void) +{ + R8_SPI0_CLOCK_DIV = 4; // Ƶʱ4Ƶ + R8_SPI0_CTRL_MOD = RB_SPI_ALL_CLEAR; + R8_SPI0_CTRL_MOD = RB_SPI_MOSI_OE | RB_SPI_SCK_OE; + R8_SPI0_CTRL_CFG |= RB_SPI_AUTO_IF; // BUFFER/FIFOԶIF_BYTE_END־ + R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE; // DMAʽ +} + +/********************************************************************* + * @fn SPI0_CLKCfg + * + * @brief SPI0 ׼ʱã= d*Tsys + * + * @param c - ʱӷƵϵ + * + * @return none + */ +void SPI0_CLKCfg(uint8_t c) +{ + if(c == 2) + { + R8_SPI0_CTRL_CFG |= RB_SPI_MST_DLY_EN; + } + else + { + R8_SPI0_CTRL_CFG &= ~RB_SPI_MST_DLY_EN; + } + R8_SPI0_CLOCK_DIV = c; +} + +/********************************************************************* + * @fn SPI0_DataMode + * + * @brief ģʽ + * + * @param m - ģʽ refer to ModeBitOrderTypeDef + * + * @return none + */ +void SPI0_DataMode(ModeBitOrderTypeDef m) +{ + switch(m) + { + case Mode0_LowBitINFront: + R8_SPI0_CTRL_MOD &= ~RB_SPI_MST_SCK_MOD; + R8_SPI0_CTRL_CFG |= RB_SPI_BIT_ORDER; + break; + case Mode0_HighBitINFront: + R8_SPI0_CTRL_MOD &= ~RB_SPI_MST_SCK_MOD; + R8_SPI0_CTRL_CFG &= ~RB_SPI_BIT_ORDER; + break; + case Mode3_LowBitINFront: + R8_SPI0_CTRL_MOD |= RB_SPI_MST_SCK_MOD; + R8_SPI0_CTRL_CFG |= RB_SPI_BIT_ORDER; + break; + case Mode3_HighBitINFront: + R8_SPI0_CTRL_MOD |= RB_SPI_MST_SCK_MOD; + R8_SPI0_CTRL_CFG &= ~RB_SPI_BIT_ORDER; + break; + default: + break; + } +} + +/********************************************************************* + * @fn SPI0_MasterSendByte + * + * @brief ͵ֽ (buffer) + * + * @param d - ֽ + * + * @return none + */ +void SPI0_MasterSendByte(uint8_t d) +{ + R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; + R8_SPI0_BUFFER = d; + while(!(R8_SPI0_INT_FLAG & RB_SPI_FREE)); +} + +/********************************************************************* + * @fn SPI0_MasterRecvByte + * + * @brief յֽ (buffer) + * + * @param none + * + * @return յֽ + */ +uint8_t SPI0_MasterRecvByte(void) +{ + R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; + R8_SPI0_BUFFER = 0xFF; // + while(!(R8_SPI0_INT_FLAG & RB_SPI_FREE)); + return (R8_SPI0_BUFFER); +} + +/********************************************************************* + * @fn SPI0_MasterTrans + * + * @brief ʹFIFOͶֽ + * + * @param pbuf - ͵׵ַ + * @param len - ͵ݳȣ4095 + * + * @return none + */ +void SPI0_MasterTrans(uint8_t *pbuf, uint16_t len) +{ + uint16_t sendlen; + + sendlen = len; + R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; // ݷΪ + R16_SPI0_TOTAL_CNT = sendlen; // Ҫ͵ݳ + R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END; + while(sendlen) + { + if(R8_SPI0_FIFO_COUNT < SPI_FIFO_SIZE) + { + R8_SPI0_FIFO = *pbuf; + pbuf++; + sendlen--; + } + } + while(R8_SPI0_FIFO_COUNT != 0); // ȴFIFOеȫ +} + +/********************************************************************* + * @fn SPI0_MasterRecv + * + * @brief ʹFIFOնֽ + * + * @param pbuf - յ׵ַ + * @param len - յݳȣ4095 + * + * @return none + */ +void SPI0_MasterRecv(uint8_t *pbuf, uint16_t len) +{ + uint16_t readlen; + + readlen = len; + R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; // ݷΪ + R16_SPI0_TOTAL_CNT = len; // ҪյݳȣFIFOΪ볤ȲΪ0 */ + R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END; + while(readlen) + { + if(R8_SPI0_FIFO_COUNT) + { + *pbuf = R8_SPI0_FIFO; + pbuf++; + readlen--; + } + } +} + +/********************************************************************* + * @fn SPI0_MasterDMATrans + * + * @brief DMAʽ + * + * @param pbuf - ʼַ,Ҫֽڶ + * @param len - ݳ + * + * @return none + */ +void SPI0_MasterDMATrans(uint8_t *pbuf, uint16_t len) +{ + R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; + R16_SPI0_DMA_BEG = (uint32_t)pbuf; + R16_SPI0_DMA_END = (uint32_t)(pbuf + len); + R16_SPI0_TOTAL_CNT = len; + R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END | RB_SPI_IF_DMA_END; + R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE; + while(!(R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END)); + R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE; +} + +/********************************************************************* + * @fn SPI0_MasterDMARecv + * + * @brief DMAʽ + * + * @param pbuf - ݴʼַ,Ҫֽڶ + * @param len - ݳ + * + * @return none + */ +void SPI0_MasterDMARecv(uint8_t *pbuf, uint16_t len) +{ + R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; + R16_SPI0_DMA_BEG = (uint32_t)pbuf; + R16_SPI0_DMA_END = (uint32_t)(pbuf + len); + R16_SPI0_TOTAL_CNT = len; + R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END | RB_SPI_IF_DMA_END; + R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE; + while(!(R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END)); + R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE; +} + +/********************************************************************* + * @fn SPI0_SlaveInit + * + * @brief 豸ģʽĬϳʼMISOGPIOӦΪģʽ + * + * @return none + */ +void SPI0_SlaveInit(void) +{ + R8_SPI0_CTRL_MOD = RB_SPI_ALL_CLEAR; + R8_SPI0_CTRL_MOD = RB_SPI_MISO_OE | RB_SPI_MODE_SLAVE; + R8_SPI0_CTRL_CFG |= RB_SPI_AUTO_IF; +} + +/********************************************************************* + * @fn SPI0_SlaveRecvByte + * + * @brief ӻģʽһֽ + * + * @return յ + */ +uint8_t SPI0_SlaveRecvByte(void) +{ + R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; + while(R8_SPI0_FIFO_COUNT == 0); + return R8_SPI0_FIFO; +} + +/********************************************************************* + * @fn SPI0_SlaveSendByte + * + * @brief ӻģʽһֽ + * + * @param d - + * + * @return none + */ +void SPI0_SlaveSendByte(uint8_t d) +{ + R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; + R8_SPI0_FIFO = d; + while(R8_SPI0_FIFO_COUNT != 0); // ȴ +} + +/********************************************************************* + * @fn SPI0_SlaveRecv + * + * @brief ӻģʽնֽ + * + * @param pbuf - ݴʼַ + * @param len - ݳ + * + * @return none + */ +void SPI0_SlaveRecv(uint8_t *pbuf, uint16_t len) +{ + uint16_t revlen; + + revlen = len; + R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; + R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END; + while(revlen) + { + if(R8_SPI0_FIFO_COUNT) + { + *pbuf = R8_SPI0_FIFO; + pbuf++; + revlen--; + } + } +} + +/********************************************************************* + * @fn SPI0_SlaveTrans + * + * @brief ӻģʽͶֽ + * + * @param pbuf - ͵׵ַ + * @param len - ͵ݳȣ4095 + * + * @return none + */ +void SPI0_SlaveTrans(uint8_t *pbuf, uint16_t len) +{ + uint16_t sendlen; + + sendlen = len; + R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; // ݷΪ + R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END; + while(sendlen) + { + if(R8_SPI0_FIFO_COUNT < SPI_FIFO_SIZE) + { + R8_SPI0_FIFO = *pbuf; + pbuf++; + sendlen--; + } + } + while(R8_SPI0_FIFO_COUNT != 0); // ȴFIFOеȫ +} + +/********************************************************************* + * @fn SPI0_SlaveDMARecv + * + * @brief DMAʽ + * + * @param pbuf - ݴʼַ,Ҫֽڶ + * @param len - ݳ + * + * @return none + */ +void SPI0_SlaveDMARecv(uint8_t *pbuf, uint16_t len) +{ + R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; + R16_SPI0_DMA_BEG = (uint32_t)pbuf; + R16_SPI0_DMA_END = (uint32_t)(pbuf + len); + R16_SPI0_TOTAL_CNT = len; + R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END | RB_SPI_IF_DMA_END; + R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE; + while(!(R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END)); + R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE; +} + +/********************************************************************* + * @fn SPI0_SlaveDMATrans + * + * @brief DMAʽ + * + * @param pbuf - ʼַ,Ҫֽڶ + * @param len - ݳ + * + * @return none + */ +void SPI0_SlaveDMATrans(uint8_t *pbuf, uint16_t len) +{ + R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; + R16_SPI0_DMA_BEG = (uint32_t)pbuf; + R16_SPI0_DMA_END = (uint32_t)(pbuf + len); + R16_SPI0_TOTAL_CNT = len; + R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END | RB_SPI_IF_DMA_END; + R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE; + while(!(R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END)); + R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE; +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi1.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi1.c new file mode 100644 index 0000000..e96b9e0 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi1.c @@ -0,0 +1,178 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_SPI1.c + * Author : WCH + * Version : V1.0 + * Date : 2018/12/15 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn SPI1_MasterDefInit + * + * @brief ģʽĬϳʼģʽ0+3ȫ˫+8MHz + * + * @param none + * + * @return none + */ +void SPI1_MasterDefInit(void) +{ + R8_SPI1_CLOCK_DIV = 4; // Ƶʱ4Ƶ + R8_SPI1_CTRL_MOD = RB_SPI_ALL_CLEAR; + R8_SPI1_CTRL_MOD = RB_SPI1_SDO_OE | RB_SPI_SCK_OE; + R8_SPI1_CTRL_CFG |= RB_SPI_AUTO_IF; // BUFFER/FIFOԶIF_BYTE_END־ +} + +/********************************************************************* + * @fn SPI1_CLKCfg + * + * @brief SPI1 ׼ʱã= d*Tsys + * + * @param c - ʱӷƵϵ + * + * @return none + */ +void SPI1_CLKCfg(uint8_t c) +{ + if(c == 2) + { + R8_SPI1_CTRL_CFG |= RB_SPI_MST_DLY_EN; + } + else + { + R8_SPI1_CTRL_CFG &= ~RB_SPI_MST_DLY_EN; + } + R8_SPI1_CLOCK_DIV = c; +} + +/********************************************************************* + * @fn SPI1_DataMode + * + * @brief ģʽ + * + * @param m - ģʽ refer to ModeBitOrderTypeDef + * + * @return none + */ +void SPI1_DataMode(ModeBitOrderTypeDef m) +{ + switch(m) + { + case Mode0_LowBitINFront: + R8_SPI1_CTRL_MOD &= ~RB_SPI_MST_SCK_MOD; + R8_SPI1_CTRL_CFG |= RB_SPI_BIT_ORDER; + break; + case Mode0_HighBitINFront: + R8_SPI1_CTRL_MOD &= ~RB_SPI_MST_SCK_MOD; + R8_SPI1_CTRL_CFG &= ~RB_SPI_BIT_ORDER; + break; + case Mode3_LowBitINFront: + R8_SPI1_CTRL_MOD |= RB_SPI_MST_SCK_MOD; + R8_SPI1_CTRL_CFG |= RB_SPI_BIT_ORDER; + break; + case Mode3_HighBitINFront: + R8_SPI1_CTRL_MOD |= RB_SPI_MST_SCK_MOD; + R8_SPI1_CTRL_CFG &= ~RB_SPI_BIT_ORDER; + break; + default: + break; + } +} + +/********************************************************************* + * @fn SPI1_MasterSendByte + * + * @brief ͵ֽ (buffer) + * + * @param d - ֽ + * + * @return none + */ +void SPI1_MasterSendByte(uint8_t d) +{ + R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR; + R8_SPI1_BUFFER = d; + while(!(R8_SPI1_INT_FLAG & RB_SPI_FREE)); +} + +/********************************************************************* + * @fn SPI1_MasterRecvByte + * + * @brief յֽ (buffer) + * + * @param none + * + * @return յֽ + */ +uint8_t SPI1_MasterRecvByte(void) +{ + R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR; + R8_SPI1_BUFFER = 0xFF; // + while(!(R8_SPI1_INT_FLAG & RB_SPI_FREE)); + return (R8_SPI1_BUFFER); +} + +/********************************************************************* + * @fn SPI1_MasterTrans + * + * @brief ʹFIFOͶֽ + * + * @param pbuf - ͵׵ַ + * @param len - ͵ݳȣ4095 + * + * @return none + */ +void SPI1_MasterTrans(uint8_t *pbuf, uint16_t len) +{ + uint16_t sendlen; + + sendlen = len; + R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR; // ݷΪ + R16_SPI1_TOTAL_CNT = sendlen; // Ҫ͵ݳ + R8_SPI1_INT_FLAG = RB_SPI_IF_CNT_END; + while(sendlen) + { + if(R8_SPI1_FIFO_COUNT < SPI_FIFO_SIZE) + { + R8_SPI1_FIFO = *pbuf; + pbuf++; + sendlen--; + } + } + while(R8_SPI1_FIFO_COUNT != 0); // ȴFIFOеȫ +} + +/********************************************************************* + * @fn SPI1_MasterRecv + * + * @brief ʹFIFOնֽ + * + * @param pbuf - յ׵ַ + * @param len - յݳȣ4095 + * + * @return none + */ +void SPI1_MasterRecv(uint8_t *pbuf, uint16_t len) +{ + uint16_t readlen; + + readlen = len; + R8_SPI1_CTRL_MOD |= RB_SPI_FIFO_DIR; // ݷΪ + R16_SPI1_TOTAL_CNT = len; // ҪյݳȣFIFOΪ볤ȲΪ0 */ + R8_SPI1_INT_FLAG = RB_SPI_IF_CNT_END; + while(readlen) + { + if(R8_SPI1_FIFO_COUNT) + { + *pbuf = R8_SPI1_FIFO; + pbuf++; + readlen--; + } + } +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_sys.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_sys.c new file mode 100644 index 0000000..9ec9509 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_sys.c @@ -0,0 +1,371 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_SYS.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn SetSysClock + * + * @brief ϵͳʱ + * + * @param sc - ϵͳʱԴѡ refer to SYS_CLKTypeDef + * + * @return none + */ +__HIGH_CODE +void SetSysClock(SYS_CLKTypeDef sc) +{ + uint32_t i; + sys_safe_access_enable(); + R8_PLL_CONFIG &= ~(1 << 5); // + sys_safe_access_disable(); + if(sc & 0x20) + { // HSE div + if(!(R8_HFCK_PWR_CTRL & RB_CLK_XT32M_PON)) + { + sys_safe_access_enable(); + R8_HFCK_PWR_CTRL |= RB_CLK_XT32M_PON; // HSE power on + for(i = 0; i < 1200; i++) + { + __nop(); + __nop(); + } + } + + sys_safe_access_enable(); + R16_CLK_SYS_CFG = (0 << 6) | (sc & 0x1f); + __nop(); + __nop(); + __nop(); + __nop(); + sys_safe_access_disable(); + sys_safe_access_enable(); + SAFEOPERATE; + R8_FLASH_CFG = 0X51; + sys_safe_access_disable(); + } + + else if(sc & 0x40) + { // PLL div + if(!(R8_HFCK_PWR_CTRL & RB_CLK_PLL_PON)) + { + sys_safe_access_enable(); + R8_HFCK_PWR_CTRL |= RB_CLK_PLL_PON; // PLL power on + for(i = 0; i < 2000; i++) + { + __nop(); + __nop(); + } + } + sys_safe_access_enable(); + R16_CLK_SYS_CFG = (1 << 6) | (sc & 0x1f); + __nop(); + __nop(); + __nop(); + __nop(); + sys_safe_access_disable(); + if(sc == CLK_SOURCE_PLL_80MHz) + { + sys_safe_access_enable(); + R8_FLASH_CFG = 0X02; + sys_safe_access_disable(); + } + else + { + sys_safe_access_enable(); + R8_FLASH_CFG = 0X52; + sys_safe_access_disable(); + } + } + else + { + sys_safe_access_enable(); + R16_CLK_SYS_CFG |= RB_CLK_SYS_MOD; + } + //FLASH clk + sys_safe_access_enable(); + R8_PLL_CONFIG |= 1 << 7; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn GetSysClock + * + * @brief ȡǰϵͳʱ + * + * @param none + * + * @return Hz + */ +uint32_t GetSysClock(void) +{ + uint16_t rev; + + rev = R16_CLK_SYS_CFG & 0xff; + if((rev & 0x40) == (0 << 6)) + { // 32MзƵ + return (32000000 / (rev & 0x1f)); + } + else if((rev & RB_CLK_SYS_MOD) == (1 << 6)) + { // PLLзƵ + return (480000000 / (rev & 0x1f)); + } + else + { // 32KƵ + return (32000); + } +} + +/********************************************************************* + * @fn SYS_GetInfoSta + * + * @brief ȡǰϵͳϢ״̬ + * + * @param i - refer to SYS_InfoStaTypeDef + * + * @return Ƿ + */ +uint8_t SYS_GetInfoSta(SYS_InfoStaTypeDef i) +{ + if(i == STA_SAFEACC_ACT) + { + return (R8_SAFE_ACCESS_SIG & RB_SAFE_ACC_ACT); + } + else + { + return (R8_GLOB_CFG_INFO & (1 << i)); + } +} + +/********************************************************************* + * @fn SYS_ResetExecute + * + * @brief ִϵͳλ + * + * @param none + * + * @return none + */ +__HIGH_CODE +void SYS_ResetExecute(void) +{ + FLASH_ROM_SW_RESET(); + sys_safe_access_enable(); + R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn SYS_DisableAllIrq + * + * @brief رжϣǰжֵ + * + * @param pirqv - ǰжֵ + * + * @return none + */ +void SYS_DisableAllIrq(uint32_t *pirqv) +{ + *pirqv = (PFIC->ISR[0] >> 8) | (PFIC->ISR[1] << 24); + PFIC->IRER[0] = 0xffffffff; + PFIC->IRER[1] = 0xffffffff; +} + +/********************************************************************* + * @fn SYS_RecoverIrq + * + * @brief ָ֮ǰرյжֵ + * + * @param irq_status - ǰжֵ + * + * @return none + */ +void SYS_RecoverIrq(uint32_t irq_status) +{ + PFIC->IENR[0] = (irq_status << 8); + PFIC->IENR[1] = (irq_status >> 24); +} + +/********************************************************************* + * @fn SYS_GetSysTickCnt + * + * @brief ȡǰϵͳ(SYSTICK)ֵ + * + * @param none + * + * @return ǰֵ + */ +uint32_t SYS_GetSysTickCnt(void) +{ + uint32_t val; + + val = SysTick->CNT; + return (val); +} + +/********************************************************************* + * @fn WWDG_ITCfg + * + * @brief Źʱжʹ + * + * @param s - Ƿж + * + * @return none + */ +void WWDG_ITCfg(FunctionalState s) +{ + uint8_t ctrl = R8_RST_WDOG_CTRL; + + if(s == DISABLE) + { + ctrl &= ~RB_WDOG_INT_EN; + } + else + { + ctrl |= RB_WDOG_INT_EN; + } + + sys_safe_access_enable(); + R8_RST_WDOG_CTRL = ctrl; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn WWDG_ResetCfg + * + * @brief Źʱλ + * + * @param s - Ƿλ + * + * @return none + */ +void WWDG_ResetCfg(FunctionalState s) +{ + uint8_t ctrl = R8_RST_WDOG_CTRL; + + if(s == DISABLE) + { + ctrl &= ~RB_WDOG_RST_EN; + } + else + { + ctrl |= RB_WDOG_RST_EN; + } + + sys_safe_access_enable(); + R8_RST_WDOG_CTRL = ctrl; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn WWDG_ClearFlag + * + * @brief Źжϱ־¼ؼֵҲ + * + * @param none + * + * @return none + */ +void WWDG_ClearFlag(void) +{ + sys_safe_access_enable(); + R8_RST_WDOG_CTRL |= RB_WDOG_INT_FLAG; + sys_safe_access_disable(); +} + +/********************************************************************* + * @fn HardFault_Handler + * + * @brief ӲжϣִиλλΪϵ縴λ + * + * @param none + * + * @return none + */ +__INTERRUPT +__HIGH_CODE +__attribute__((weak)) +void HardFault_Handler(void) +{ + FLASH_ROM_SW_RESET(); + sys_safe_access_enable(); + R16_INT32K_TUNE = 0xFFFF; + sys_safe_access_enable(); + R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET; + sys_safe_access_disable(); + while(1); +} + +/********************************************************************* + * @fn mDelayuS + * + * @brief uS ʱ + * + * @param t - ʱ + * + * @return none + */ +__HIGH_CODE +void mDelayuS(uint16_t t) +{ + uint32_t i; +#if(FREQ_SYS == 80000000) + i = t * 20; +#elif(FREQ_SYS == 60000000) + i = t * 15; +#elif(FREQ_SYS == 48000000) + i = t * 12; +#elif(FREQ_SYS == 40000000) + i = t * 10; +#elif(FREQ_SYS == 32000000) + i = t << 3; +#elif(FREQ_SYS == 24000000) + i = t * 6; +#elif(FREQ_SYS == 16000000) + i = t << 2; +#elif(FREQ_SYS == 8000000) + i = t << 1; +#elif(FREQ_SYS == 4000000) + i = t; +#elif(FREQ_SYS == 2000000) + i = t >> 1; +#elif(FREQ_SYS == 1000000) + i = t >> 2; +#else + i = t << 1; +#endif + do + { + __nop(); + } while(--i); +} + +/********************************************************************* + * @fn mDelaymS + * + * @brief mS ʱ + * + * @param t - ʱ + * + * @return none + */ +__HIGH_CODE +void mDelaymS(uint16_t t) +{ + uint16_t i; + + for(i = 0; i < t; i++) + { + mDelayuS(1000); + } +} + diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer0.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer0.c new file mode 100644 index 0000000..07c3fb9 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer0.c @@ -0,0 +1,75 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_timer0.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn TMR0_TimerInit + * + * @brief ʱܳʼ + * + * @param t - ʱʱ䣬ڵǰϵͳʱTsys, ʱ 67108864 + * + * @return none + */ +void TMR0_TimerInit(uint32_t t) +{ + R32_TMR0_CNT_END = t; + R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR0_CTRL_MOD = RB_TMR_COUNT_EN; +} + +/********************************************************************* + * @fn TMR0_EXTSingleCounterInit + * + * @brief ؼܳʼ + * + * @param cap - ɼ + * + * @return none + */ +void TMR0_EXTSingleCounterInit(CapModeTypeDef cap) +{ + R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR0_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_CAP_COUNT | RB_TMR_MODE_IN | (cap << 6); +} + +/********************************************************************* + * @fn TMR0_PWMInit + * + * @brief PWM ʼ + * + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param ts - set pwm repeat times, refer to PWM_RepeatTsTypeDef + * + * @return none + */ +void TMR0_PWMInit(PWMX_PolarTypeDef pr, PWM_RepeatTsTypeDef ts) +{ + // R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR0_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_OUT_EN | (pr << 4) | (ts << 6); +} + +/********************************************************************* + * @fn TMR0_CapInit + * + * @brief ⲿźŲ׽ܳʼ + * + * @param cap - select capture mode, refer to CapModeTypeDef + * + * @return none + */ +void TMR0_CapInit(CapModeTypeDef cap) +{ + R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR0_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_MODE_IN | (cap << 6); +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer1.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer1.c new file mode 100644 index 0000000..fff4d79 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer1.c @@ -0,0 +1,104 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_timer1.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn TMR1_TimerInit + * + * @brief ʱܳʼ + * + * @param t - ʱʱ䣬ڵǰϵͳʱTsys, ʱ 67108864 + * + * @return none + */ +void TMR1_TimerInit(uint32_t t) +{ + R32_TMR1_CNT_END = t; + R8_TMR1_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR1_CTRL_MOD = RB_TMR_COUNT_EN; +} + +/********************************************************************* + * @fn TMR1_EXTSingleCounterInit + * + * @brief ؼܳʼ + * + * @param cap - ɼ + * + * @return none + */ +void TMR1_EXTSingleCounterInit(CapModeTypeDef cap) +{ + R8_TMR1_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR1_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_CAP_COUNT | RB_TMR_MODE_IN | (cap << 6); +} + +/********************************************************************* + * @fn TMR1_PWMInit + * + * @brief PWM ʼ + * + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param ts - set pwm repeat times, refer to PWM_RepeatTsTypeDef + * + * @return none + */ +void TMR1_PWMInit(PWMX_PolarTypeDef pr, PWM_RepeatTsTypeDef ts) +{ + // R8_TMR1_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR1_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_OUT_EN | (pr << 4) | (ts << 6); +} + +/********************************************************************* + * @fn TMR1_CapInit + * + * @brief ⲿźŲ׽ܳʼ + * + * @param cap - select capture mode, refer to CapModeTypeDef + * + * @return none + */ +void TMR1_CapInit(CapModeTypeDef cap) +{ + R8_TMR1_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR1_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_MODE_IN | (cap << 6); +} + +/********************************************************************* + * @fn TMR1_DMACfg + * + * @brief DMA + * + * @param s - ǷDMA + * @param startAddr - DMA ʼַ + * @param endAddr - DMA ַ + * @param m - DMAģʽ + * + * @return none + */ +void TMR1_DMACfg(uint8_t s, uint16_t startAddr, uint16_t endAddr, DMAModeTypeDef m) +{ + if(s == DISABLE) + { + R8_TMR1_CTRL_DMA = 0; + } + else + { + R16_TMR1_DMA_BEG = startAddr; + R16_TMR1_DMA_END = endAddr; + if(m) + R8_TMR1_CTRL_DMA = RB_TMR_DMA_LOOP | RB_TMR_DMA_ENABLE; + else + R8_TMR1_CTRL_DMA = RB_TMR_DMA_ENABLE; + } +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer2.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer2.c new file mode 100644 index 0000000..3ef20d1 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer2.c @@ -0,0 +1,104 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_timer2.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn TMR2_TimerInit + * + * @brief ʱܳʼ + * + * @param t - ʱʱ䣬ڵǰϵͳʱTsys, ʱ 67108864 + * + * @return none + */ +void TMR2_TimerInit(uint32_t t) +{ + R32_TMR2_CNT_END = t; + R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN; +} + +/********************************************************************* + * @fn TMR2_EXTSingleCounterInit + * + * @brief ؼܳʼ + * + * @param cap - ɼ + * + * @return none + */ +void TMR2_EXTSingleCounterInit(CapModeTypeDef cap) +{ + R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_CAP_COUNT | RB_TMR_MODE_IN | (cap << 6); +} + +/********************************************************************* + * @fn TMR2_PWMInit + * + * @brief PWM ʼ + * + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param ts - set pwm repeat times, refer to PWM_RepeatTsTypeDef + * + * @return none + */ +void TMR2_PWMInit(PWMX_PolarTypeDef pr, PWM_RepeatTsTypeDef ts) +{ + // R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_OUT_EN | (pr << 4) | (ts << 6); +} + +/********************************************************************* + * @fn TMR2_CapInit + * + * @brief ⲿźŲ׽ܳʼ + * + * @param cap - select capture mode, refer to CapModeTypeDef + * + * @return none + */ +void TMR2_CapInit(CapModeTypeDef cap) +{ + R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_MODE_IN | (cap << 6); +} + +/********************************************************************* + * @fn TMR2_DMACfg + * + * @brief DMA + * + * @param s - ǷDMA + * @param startAddr - DMA ʼַ + * @param endAddr - DMA ַ + * @param m - DMAģʽ + * + * @return none + */ +void TMR2_DMACfg(uint8_t s, uint16_t startAddr, uint16_t endAddr, DMAModeTypeDef m) +{ + if(s == DISABLE) + { + R8_TMR2_CTRL_DMA = 0; + } + else + { + R16_TMR2_DMA_BEG = startAddr; + R16_TMR2_DMA_END = endAddr; + if(m) + R8_TMR2_CTRL_DMA = RB_TMR_DMA_LOOP | RB_TMR_DMA_ENABLE; + else + R8_TMR2_CTRL_DMA = RB_TMR_DMA_ENABLE; + } +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer3.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer3.c new file mode 100644 index 0000000..68c9140 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer3.c @@ -0,0 +1,75 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_timer3.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn TMR3_TimerInit + * + * @brief ʱܳʼ + * + * @param t - ʱʱ䣬ڵǰϵͳʱTsys, ʱ 67108864 + * + * @return none + */ +void TMR3_TimerInit(uint32_t t) +{ + R32_TMR3_CNT_END = t; + R8_TMR3_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR3_CTRL_MOD = RB_TMR_COUNT_EN; +} + +/********************************************************************* + * @fn TMR3_EXTSingleCounterInit + * + * @brief ؼܳʼ + * + * @param cap - ɼ + * + * @return none + */ +void TMR3_EXTSingleCounterInit(CapModeTypeDef cap) +{ + R8_TMR3_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR3_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_CAP_COUNT | RB_TMR_MODE_IN | (cap << 6); +} + +/********************************************************************* + * @fn TMR3_PWMInit + * + * @brief PWM ʼ + * + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param ts - set pwm repeat times, refer to PWM_RepeatTsTypeDef + * + * @return none + */ +void TMR3_PWMInit(PWMX_PolarTypeDef pr, PWM_RepeatTsTypeDef ts) +{ + // R8_TMR3_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR3_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_OUT_EN | (pr << 4) | (ts << 6); +} + +/********************************************************************* + * @fn TMR3_CapInit + * + * @brief ⲿźŲ׽ܳʼ + * + * @param cap - select capture mode, refer to CapModeTypeDef + * + * @return none + */ +void TMR3_CapInit(CapModeTypeDef cap) +{ + R8_TMR3_CTRL_MOD = RB_TMR_ALL_CLEAR; + R8_TMR3_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_MODE_IN | (cap << 6); +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart0.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart0.c new file mode 100644 index 0000000..546da00 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart0.c @@ -0,0 +1,151 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_uart0.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn UART0_DefInit + * + * @brief Ĭϳʼ + * + * @param none + * + * @return none + */ +void UART0_DefInit(void) +{ + UART0_BaudRateCfg(115200); + R8_UART0_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO򿪣4ֽ + R8_UART0_LCR = RB_LCR_WORD_SZ; + R8_UART0_IER = RB_IER_TXD_EN; + R8_UART0_DIV = 1; +} + +/********************************************************************* + * @fn UART0_BaudRateCfg + * + * @brief ڲ + * + * @param baudrate - + * + * @return none + */ +void UART0_BaudRateCfg(uint32_t baudrate) +{ + uint32_t x; + + x = 10 * GetSysClock() / 8 / baudrate; + x = (x + 5) / 10; + R16_UART0_DL = (uint16_t)x; +} + +/********************************************************************* + * @fn UART0_ByteTrigCfg + * + * @brief ֽڴж + * + * @param b - ֽ refer to UARTByteTRIGTypeDef + * + * @return none + */ +void UART0_ByteTrigCfg(UARTByteTRIGTypeDef b) +{ + R8_UART0_FCR = (R8_UART0_FCR & ~RB_FCR_FIFO_TRIG) | (b << 6); +} + +/********************************************************************* + * @fn UART0_INTCfg + * + * @brief ж + * + * @param s - жϿ״̬ǷʹӦж + * @param i - ж + * RB_IER_MODEM_CHG - ƽ״̬仯жʹλ UART0 ֧֣ + * RB_IER_LINE_STAT - ·״̬ж + * RB_IER_THR_EMPTY - ͱּĴж + * RB_IER_RECV_RDY - ж + * + * @return none + */ +void UART0_INTCfg(FunctionalState s, uint8_t i) +{ + if(s) + { + R8_UART0_IER |= i; + R8_UART0_MCR |= RB_MCR_INT_OE; + } + else + { + R8_UART0_IER &= ~i; + } +} + +/********************************************************************* + * @fn UART0_Reset + * + * @brief λ + * + * @param none + * + * @return none + */ +void UART0_Reset(void) +{ + R8_UART0_IER = RB_IER_RESET; +} + +/********************************************************************* + * @fn UART0_SendString + * + * @brief ڶֽڷ + * + * @param buf - ͵׵ַ + * @param l - ͵ݳ + * + * @return none + */ +void UART0_SendString(uint8_t *buf, uint16_t l) +{ + uint16_t len = l; + + while(len) + { + if(R8_UART0_TFC != UART_FIFO_SIZE) + { + R8_UART0_THR = *buf++; + len--; + } + } +} + +/********************************************************************* + * @fn UART0_RecvString + * + * @brief ڶȡֽ + * + * @param buf - ȡݴŻ׵ַ + * + * @return ȡݳ + */ +uint16_t UART0_RecvString(uint8_t *buf) +{ + uint16_t len = 0; + + while(R8_UART0_RFC) + { + *buf++ = R8_UART0_RBR; + len++; + } + + return (len); +} + diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart1.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart1.c new file mode 100644 index 0000000..da7a22d --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart1.c @@ -0,0 +1,150 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_uart1.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn UART1_DefInit + * + * @brief Ĭϳʼ + * + * @param none + * + * @return none + */ +void UART1_DefInit(void) +{ + UART1_BaudRateCfg(115200); + R8_UART1_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO򿪣4ֽ + R8_UART1_LCR = RB_LCR_WORD_SZ; + R8_UART1_IER = RB_IER_TXD_EN; + R8_UART1_DIV = 1; +} + +/********************************************************************* + * @fn UART1_BaudRateCfg + * + * @brief ڲ + * + * @param baudrate - + * + * @return none + */ +void UART1_BaudRateCfg(uint32_t baudrate) +{ + uint32_t x; + + x = 10 * GetSysClock() / 8 / baudrate; + x = (x + 5) / 10; + R16_UART1_DL = (uint16_t)x; +} + +/********************************************************************* + * @fn UART1_ByteTrigCfg + * + * @brief ֽڴж + * + * @param b - ֽ refer to UARTByteTRIGTypeDef + * + * @return none + */ +void UART1_ByteTrigCfg(UARTByteTRIGTypeDef b) +{ + R8_UART1_FCR = (R8_UART1_FCR & ~RB_FCR_FIFO_TRIG) | (b << 6); +} + +/********************************************************************* + * @fn UART1_INTCfg + * + * @brief ж + * + * @param s - жϿ״̬ǷʹӦж + * @param i - ж + * RB_IER_MODEM_CHG - ƽ״̬仯жʹλ UART0 ֧֣ + * RB_IER_LINE_STAT - ·״̬ж + * RB_IER_THR_EMPTY - ͱּĴж + * RB_IER_RECV_RDY - ж + * + * @return none + */ +void UART1_INTCfg(FunctionalState s, uint8_t i) +{ + if(s) + { + R8_UART1_IER |= i; + R8_UART1_MCR |= RB_MCR_INT_OE; + } + else + { + R8_UART1_IER &= ~i; + } +} + +/********************************************************************* + * @fn UART1_Reset + * + * @brief λ + * + * @param none + * + * @return none + */ +void UART1_Reset(void) +{ + R8_UART1_IER = RB_IER_RESET; +} + +/********************************************************************* + * @fn UART1_SendString + * + * @brief ڶֽڷ + * + * @param buf - ͵׵ַ + * @param l - ͵ݳ + * + * @return none + */ +void UART1_SendString(uint8_t *buf, uint16_t l) +{ + uint16_t len = l; + + while(len) + { + if(R8_UART1_TFC != UART_FIFO_SIZE) + { + R8_UART1_THR = *buf++; + len--; + } + } +} + +/********************************************************************* + * @fn UART1_RecvString + * + * @brief ڶȡֽ + * + * @param buf - ȡݴŻ׵ַ + * + * @return ȡݳ + */ +uint16_t UART1_RecvString(uint8_t *buf) +{ + uint16_t len = 0; + + while(R8_UART1_RFC) + { + *buf++ = R8_UART1_RBR; + len++; + } + + return (len); +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart2.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart2.c new file mode 100644 index 0000000..baceba9 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart2.c @@ -0,0 +1,151 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_uart2.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn UART2_DefInit + * + * @brief Ĭϳʼ + * + * @param none + * + * @return none + */ +void UART2_DefInit(void) +{ + UART2_BaudRateCfg(115200); + R8_UART2_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO򿪣4ֽ + R8_UART2_LCR = RB_LCR_WORD_SZ; + R8_UART2_IER = RB_IER_TXD_EN; + R8_UART2_DIV = 1; +} + +/********************************************************************* + * @fn UART2_BaudRateCfg + * + * @brief ڲ + * + * @param baudrate - + * + * @return none + */ +void UART2_BaudRateCfg(uint32_t baudrate) +{ + uint32_t x; + + x = 10 * GetSysClock() / 8 / baudrate; + x = (x + 5) / 10; + R16_UART2_DL = (uint16_t)x; +} + +/********************************************************************* + * @fn UART2_ByteTrigCfg + * + * @brief ֽڴж + * + * @param b - ֽ refer to UARTByteTRIGTypeDef + * + * @return none + */ +void UART2_ByteTrigCfg(UARTByteTRIGTypeDef b) +{ + R8_UART2_FCR = (R8_UART2_FCR & ~RB_FCR_FIFO_TRIG) | (b << 6); +} + +/********************************************************************* + * @fn UART2_INTCfg + * + * @brief ж + * + * @param s - жϿ״̬ǷʹӦж + * @param i - ж + * RB_IER_MODEM_CHG - ƽ״̬仯жʹλ UART0 ֧֣ + * RB_IER_LINE_STAT - ·״̬ж + * RB_IER_THR_EMPTY - ͱּĴж + * RB_IER_RECV_RDY - ж + * + * @return none + */ +void UART2_INTCfg(FunctionalState s, uint8_t i) +{ + if(s) + { + R8_UART2_IER |= i; + R8_UART2_MCR |= RB_MCR_INT_OE; + } + else + { + R8_UART2_IER &= ~i; + } +} + +/********************************************************************* + * @fn UART2_Reset + * + * @brief λ + * + * @param none + * + * @return none + */ +void UART2_Reset(void) +{ + R8_UART2_IER = RB_IER_RESET; +} + +/********************************************************************* + * @fn UART2_SendString + * + * @brief ڶֽڷ + * + * @param buf - ͵׵ַ + * @param l - ͵ݳ + * + * @return none + */ +void UART2_SendString(uint8_t *buf, uint16_t l) +{ + uint16_t len = l; + + while(len) + { + if(R8_UART2_TFC != UART_FIFO_SIZE) + { + R8_UART2_THR = *buf++; + len--; + } + } +} + +/********************************************************************* + * @fn UART2_RecvString + * + * @brief ڶȡֽ + * + * @param buf - ȡݴŻ׵ַ + * + * @return ȡݳ + */ +uint16_t UART2_RecvString(uint8_t *buf) +{ + uint16_t len = 0; + + while(R8_UART2_RFC) + { + *buf++ = R8_UART2_RBR; + len++; + } + + return (len); +} + diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart3.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart3.c new file mode 100644 index 0000000..165f07e --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart3.c @@ -0,0 +1,151 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_uart3.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +/********************************************************************* + * @fn UART3_DefInit + * + * @brief Ĭϳʼ + * + * @param none + * + * @return none + */ +void UART3_DefInit(void) +{ + UART3_BaudRateCfg(115200); + R8_UART3_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO򿪣4ֽ + R8_UART3_LCR = RB_LCR_WORD_SZ; + R8_UART3_IER = RB_IER_TXD_EN; + R8_UART3_DIV = 1; +} + +/********************************************************************* + * @fn UART3_BaudRateCfg + * + * @brief ڲ + * + * @param baudrate - + * + * @return none + */ +void UART3_BaudRateCfg(uint32_t baudrate) +{ + uint32_t x; + + x = 10 * GetSysClock() / 8 / baudrate; + x = (x + 5) / 10; + R16_UART3_DL = (uint16_t)x; +} + +/********************************************************************* + * @fn UART3_ByteTrigCfg + * + * @brief ֽڴж + * + * @param b - ֽ refer to UARTByteTRIGTypeDef + * + * @return none + */ +void UART3_ByteTrigCfg(UARTByteTRIGTypeDef b) +{ + R8_UART3_FCR = (R8_UART3_FCR & ~RB_FCR_FIFO_TRIG) | (b << 6); +} + +/********************************************************************* + * @fn UART3_INTCfg + * + * @brief ж + * + * @param s - жϿ״̬ǷʹӦж + * @param i - ж + * RB_IER_MODEM_CHG - ƽ״̬仯жʹλ UART0 ֧֣ + * RB_IER_LINE_STAT - ·״̬ж + * RB_IER_THR_EMPTY - ͱּĴж + * RB_IER_RECV_RDY - ж + * + * @return none + */ +void UART3_INTCfg(FunctionalState s, uint8_t i) +{ + if(s) + { + R8_UART3_IER |= i; + R8_UART3_MCR |= RB_MCR_INT_OE; + } + else + { + R8_UART3_IER &= ~i; + } +} + +/********************************************************************* + * @fn UART3_Reset + * + * @brief λ + * + * @param none + * + * @return none + */ +void UART3_Reset(void) +{ + R8_UART3_IER = RB_IER_RESET; +} + +/********************************************************************* + * @fn UART3_SendString + * + * @brief ڶֽڷ + * + * @param buf - ͵׵ַ + * @param l - ͵ݳ + * + * @return none + */ +void UART3_SendString(uint8_t *buf, uint16_t l) +{ + uint16_t len = l; + + while(len) + { + if(R8_UART3_TFC != UART_FIFO_SIZE) + { + R8_UART3_THR = *buf++; + len--; + } + } +} + +/********************************************************************* + * @fn UART3_RecvString + * + * @brief ڶȡֽ + * + * @param buf - ȡݴŻ׵ַ + * + * @return ȡݳ + */ +uint16_t UART3_RecvString(uint8_t *buf) +{ + uint16_t len = 0; + + while(R8_UART3_RFC) + { + *buf++ = R8_UART3_RBR; + len++; + } + + return (len); +} + diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2dev.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2dev.c new file mode 100644 index 0000000..02e9682 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2dev.c @@ -0,0 +1,113 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_usb2dev.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" + +uint8_t *pU2EP0_RAM_Addr; +uint8_t *pU2EP1_RAM_Addr; +uint8_t *pU2EP2_RAM_Addr; +uint8_t *pU2EP3_RAM_Addr; + +/********************************************************************* + * @fn USB2_DeviceInit + * + * @brief USB2豸ܳʼ4˵㣬8ͨ + * + * @param none + * + * @return none + */ +void USB2_DeviceInit(void) +{ + R8_USB2_CTRL = 0x00; // 趨ģʽ,ȡ RB_UC_CLR_ALL + + R8_U2EP4_1_MOD = RB_UEP4_RX_EN | RB_UEP4_TX_EN | RB_UEP1_RX_EN | RB_UEP1_TX_EN; // ˵4 OUT+IN,˵1 OUT+IN + R8_U2EP2_3_MOD = RB_UEP2_RX_EN | RB_UEP2_TX_EN | RB_UEP3_RX_EN | RB_UEP3_TX_EN; // ˵2 OUT+IN,˵3 OUT+IN + + R16_U2EP0_DMA = (uint16_t)(uint32_t)pU2EP0_RAM_Addr; + R16_U2EP1_DMA = (uint16_t)(uint32_t)pU2EP1_RAM_Addr; + R16_U2EP2_DMA = (uint16_t)(uint32_t)pU2EP2_RAM_Addr; + R16_U2EP3_DMA = (uint16_t)(uint32_t)pU2EP3_RAM_Addr; + + R8_U2EP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; + R8_U2EP1_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG; + R8_U2EP2_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG; + R8_U2EP3_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG; + R8_U2EP4_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; + + R8_USB2_DEV_AD = 0x00; + R8_USB2_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN; // USB豸DMAжڼжϱ־δǰԶNAK + R16_PIN_ANALOG_IE |= RB_PIN_USB2_IE | RB_PIN_USB2_DP_PU; // ֹUSB˿ڸռ + R8_USB2_INT_FG = 0xFF; // жϱ־ + R8_U2DEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; // USB˿ + R8_USB2_INT_EN = RB_UIE_SUSPEND | RB_UIE_BUS_RST | RB_UIE_TRANSFER; +} + +/********************************************************************* + * @fn U2DevEP1_IN_Deal + * + * @brief U2˵1ϴ + * + * @param l - ϴݳ(<64B) + * + * @return none + */ +void U2DevEP1_IN_Deal(uint8_t l) +{ + R8_U2EP1_T_LEN = l; + R8_U2EP1_CTRL = (R8_U2EP1_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; +} + +/********************************************************************* + * @fn U2DevEP2_IN_Deal + * + * @brief U2˵2ϴ + * + * @param l - ϴݳ(<64B) + * + * @return none + */ +void U2DevEP2_IN_Deal(uint8_t l) +{ + R8_U2EP2_T_LEN = l; + R8_U2EP2_CTRL = (R8_U2EP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; +} + +/********************************************************************* + * @fn U2DevEP3_IN_Deal + * + * @brief U2˵3ϴ + * + * @param l - ϴݳ(<64B) + * + * @return none + */ +void U2DevEP3_IN_Deal(uint8_t l) +{ + R8_U2EP3_T_LEN = l; + R8_U2EP3_CTRL = (R8_U2EP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; +} + +/********************************************************************* + * @fn U2DevEP4_IN_Deal + * + * @brief U2˵4ϴ + * + * @param l - ϴݳ(<64B) + * + * @return none + */ +void U2DevEP4_IN_Deal(uint8_t l) +{ + R8_U2EP4_T_LEN = l; + R8_U2EP4_CTRL = (R8_U2EP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostBase.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostBase.c new file mode 100644 index 0000000..6aad878 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostBase.c @@ -0,0 +1,652 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_usbhost.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" +#if DISK_LIB_ENABLE + #include "CHRV3UFI.H" +#endif + +uint8_t Usb2DevEndp0Size; // USB2豸Ķ˵0ߴ +uint8_t FoundNewU2Dev; +_RootHubDev ThisUsb2Dev; //ROOT +_DevOnHubPort DevOnU2HubPort[HUB_MAX_PORTS]; // ٶ:1ⲿHUB,ÿⲿHUBHUB_MAX_PORTS˿(˲) + +uint8_t *pU2HOST_RX_RAM_Addr; +uint8_t *pU2HOST_TX_RAM_Addr; + +/*ȡ豸*/ +__attribute__((aligned(4))) const uint8_t SetupGetU2DevDescr[] = {USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, + USB_DESCR_TYP_DEVICE, 0x00, 0x00, sizeof(USB_DEV_DESCR), 0x00}; +/*ȡ*/ +__attribute__((aligned(4))) const uint8_t SetupGetU2CfgDescr[] = {USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, + USB_DESCR_TYP_CONFIG, 0x00, 0x00, 0x04, 0x00}; +/*USBַ*/ +__attribute__((aligned(4))) const uint8_t SetupSetUsb2Addr[] = {USB_REQ_TYP_OUT, USB_SET_ADDRESS, USB_DEVICE_ADDR, + 0x00, 0x00, 0x00, 0x00, 0x00}; +/*USB*/ +__attribute__((aligned(4))) const uint8_t SetupSetUsb2Config[] = {USB_REQ_TYP_OUT, USB_SET_CONFIGURATION, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +/*USBӿ*/ +__attribute__((aligned(4))) const uint8_t SetupSetUsb2Interface[] = {USB_REQ_RECIP_INTERF, USB_SET_INTERFACE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +/*˵STALL*/ +__attribute__((aligned(4))) const uint8_t SetupClrU2EndpStall[] = {USB_REQ_TYP_OUT | USB_REQ_RECIP_ENDP, USB_CLEAR_FEATURE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/********************************************************************* + * @fn DisableRootU2HubPort + * + * @brief رROOT-HUB˿,ʵӲѾԶر,˴ֻһЩṹ״̬ + * + * @param none + * + * @return none + */ +void DisableRootU2HubPort(void) +{ +#ifdef FOR_ROOT_UDISK_ONLY + CHRV3DiskStatus = DISK_DISCONNECT; +#endif +#ifndef DISK_BASE_BUF_LEN + ThisUsb2Dev.DeviceStatus = ROOT_DEV_DISCONNECT; + ThisUsb2Dev.DeviceAddress = 0x00; +#endif +} + +/********************************************************************* + * @fn AnalyzeRootU2Hub + * + * @brief ROOT-HUB״̬,ROOT-HUB˿ڵ豸¼ + * 豸γ,еDisableRootHubPort(),˿ڹر,¼,Ӧ˿ڵ״̬λ + * + * @param none + * + * @return ERR_SUCCESSΪû,ERR_USB_CONNECTΪ⵽,ERR_USB_DISCONΪ⵽Ͽ + */ +uint8_t AnalyzeRootU2Hub(void) +{ + uint8_t s; + + s = ERR_SUCCESS; + + if(R8_USB2_MIS_ST & RB_UMS_DEV_ATTACH) + { // 豸 +#ifdef DISK_BASE_BUF_LEN + if(CHRV3DiskStatus == DISK_DISCONNECT +#else + if(ThisUsb2Dev.DeviceStatus == ROOT_DEV_DISCONNECT // ⵽豸 +#endif + || (R8_U2HOST_CTRL & RB_UH_PORT_EN) == 0x00) + { // ⵽豸,δ,˵Ǹղ + DisableRootU2HubPort(); // رն˿ +#ifdef DISK_BASE_BUF_LEN + CHRV3DiskStatus = DISK_CONNECT; +#else + ThisUsb2Dev.DeviceSpeed = R8_USB2_MIS_ST & RB_UMS_DM_LEVEL ? 0 : 1; + ThisUsb2Dev.DeviceStatus = ROOT_DEV_CONNECTED; //ӱ־ +#endif + PRINT("USB2 dev in\n"); + s = ERR_USB_CONNECT; + } + } + +#ifdef DISK_BASE_BUF_LEN + else if(CHRV3DiskStatus >= DISK_CONNECT) + { +#else + else if(ThisUsb2Dev.DeviceStatus >= ROOT_DEV_CONNECTED) + { //⵽豸γ +#endif + DisableRootU2HubPort(); // رն˿ + PRINT("USB2 dev out\n"); + if(s == ERR_SUCCESS) + s = ERR_USB_DISCON; + } + // R8_USB_INT_FG = RB_UIF_DETECT; // жϱ־ + return (s); +} + +/********************************************************************* + * @fn SetHostUsb2Addr + * + * @brief USBǰUSB豸ַ + * + * @param addr - USB豸ַ + * + * @return none + */ +void SetHostUsb2Addr(uint8_t addr) +{ + R8_USB2_DEV_AD = (R8_USB2_DEV_AD & RB_UDA_GP_BIT) | (addr & MASK_USB_ADDR); +} + +/********************************************************************* + * @fn SetUsb2Speed + * + * @brief õǰUSBٶ + * + * @param FullSpeed - USBٶ + * + * @return none + */ +void SetUsb2Speed(uint8_t FullSpeed) +{ +#ifndef DISK_BASE_BUF_LEN + if(FullSpeed) // ȫ + { + R8_USB2_CTRL &= ~RB_UC_LOW_SPEED; // ȫ + R8_U2H_SETUP &= ~RB_UH_PRE_PID_EN; // ֹPRE PID + } + else + { + R8_USB2_CTRL |= RB_UC_LOW_SPEED; // + } +#endif + (void)FullSpeed; +} + +/********************************************************************* + * @fn ResetRootU2HubPort + * + * @brief ⵽豸,λ,Ϊö豸׼,ΪĬΪȫ + * + * @param none + * + * @return none + */ +void ResetRootU2HubPort(void) +{ + Usb2DevEndp0Size = DEFAULT_ENDP0_SIZE; //USB2豸Ķ˵0ߴ + SetHostUsb2Addr(0x00); + R8_U2HOST_CTRL &= ~RB_UH_PORT_EN; // ص˿ + SetUsb2Speed(1); // ĬΪȫ + R8_U2HOST_CTRL = (R8_U2HOST_CTRL & ~RB_UH_LOW_SPEED) | RB_UH_BUS_RESET; // ĬΪȫ,ʼλ + mDelaymS(15); // λʱ10mS20mS + R8_U2HOST_CTRL = R8_U2HOST_CTRL & ~RB_UH_BUS_RESET; // λ + mDelayuS(250); + R8_USB2_INT_FG = RB_UIF_DETECT; // жϱ־ +} + +/********************************************************************* + * @fn EnableRootU2HubPort + * + * @brief ʹROOT-HUB˿,ӦbUH_PORT_EN1˿,豸Ͽܵ·ʧ + * + * @param none + * + * @return ERR_SUCCESSΪ⵽,ERR_USB_DISCONΪ + */ +uint8_t EnableRootU2HubPort(void) +{ +#ifdef DISK_BASE_BUF_LEN + if(CHRV3DiskStatus < DISK_CONNECT) + CHRV3DiskStatus = DISK_CONNECT; +#else + if(ThisUsb2Dev.DeviceStatus < ROOT_DEV_CONNECTED) + ThisUsb2Dev.DeviceStatus = ROOT_DEV_CONNECTED; +#endif + if(R8_USB2_MIS_ST & RB_UMS_DEV_ATTACH) + { // 豸 +#ifndef DISK_BASE_BUF_LEN + if((R8_U2HOST_CTRL & RB_UH_PORT_EN) == 0x00) + { // δʹ + ThisUsb2Dev.DeviceSpeed = (R8_USB2_MIS_ST & RB_UMS_DM_LEVEL) ? 0 : 1; + if(ThisUsb2Dev.DeviceSpeed == 0) + R8_U2HOST_CTRL |= RB_UH_LOW_SPEED; // + } +#endif + R8_U2HOST_CTRL |= RB_UH_PORT_EN; //ʹHUB˿ + return (ERR_SUCCESS); + } + return (ERR_USB_DISCON); +} + +#ifndef DISK_BASE_BUF_LEN +/********************************************************************* + * @fn SelectU2HubPort + * + * @brief ѡҪHUB + * + * @param HubPortIndex - ѡָROOT-HUB˿ڵⲿHUBָ˿ + * + * @return None + */ +void SelectU2HubPort(uint8_t HubPortIndex) +{ + if(HubPortIndex) // ѡָROOT-HUB˿ڵⲿHUBָ˿ + { + SetHostUsb2Addr(DevOnU2HubPort[HubPortIndex - 1].DeviceAddress); // USBǰUSB豸ַ + SetUsb2Speed(DevOnU2HubPort[HubPortIndex - 1].DeviceSpeed); // õǰUSBٶ + if(DevOnU2HubPort[HubPortIndex - 1].DeviceSpeed == 0) // ͨⲿHUBUSB豸ͨѶҪǰID + { + R8_U2EP1_CTRL |= RB_UH_PRE_PID_EN; // PRE PID + mDelayuS(100); + } + } + else + { + SetHostUsb2Addr(ThisUsb2Dev.DeviceAddress); // USBǰUSB豸ַ + SetUsb2Speed(ThisUsb2Dev.DeviceSpeed); // USB豸ٶ + } +} +#endif + +/********************************************************************* + * @fn WaitUSB2_Interrupt + * + * @brief ȴUSBж + * + * @param none + * + * @return ERR_SUCCESS ݽջ߷ͳɹ,ERR_USB_UNKNOWN ݽջ߷ʧ + */ +uint8_t WaitUSB2_Interrupt(void) +{ + uint16_t i; + for(i = WAIT_USB_TOUT_200US; i != 0 && (R8_USB2_INT_FG & RB_UIF_TRANSFER) == 0; i--) + { + ; + } + return ((R8_USB2_INT_FG & RB_UIF_TRANSFER) ? ERR_SUCCESS : ERR_USB_UNKNOWN); +} + +/********************************************************************* + * @fn USB2HostTransact + * + * @brief ,ĿĶ˵ַ/PID,ͬ־,20uSΪλNAKʱ(0,0xFFFF),0ɹ,ʱ/ + * ӳ,ʵӦ,Ϊṩٶ,ӦöԱӳŻ + * + * @param endp_pid - ƺ͵ַ, 4λtoken_pid, 4λǶ˵ַ + * @param tog - ͬ־ + * @param timeout - ʱʱ + * + * @return ERR_USB_UNKNOWN ʱӲ쳣 + * ERR_USB_DISCON 豸Ͽ + * ERR_USB_CONNECT 豸 + * ERR_SUCCESS + */ +uint8_t USB2HostTransact(uint8_t endp_pid, uint8_t tog, uint32_t timeout) +{ + uint8_t TransRetry; + + uint8_t s, r; + uint16_t i; + + R8_U2H_RX_CTRL = R8_U2H_TX_CTRL = tog; + TransRetry = 0; + + do + { + R8_U2H_EP_PID = endp_pid; // ָPIDĿĶ˵ + R8_USB2_INT_FG = RB_UIF_TRANSFER; + for(i = WAIT_USB_TOUT_200US; i != 0 && (R8_USB2_INT_FG & RB_UIF_TRANSFER) == 0; i--) + ; + R8_U2H_EP_PID = 0x00; // ֹͣUSB + if((R8_USB2_INT_FG & RB_UIF_TRANSFER) == 0) + { + return (ERR_USB_UNKNOWN); + } + + if(R8_USB2_INT_FG & RB_UIF_DETECT) + { // USB豸¼ + // mDelayuS( 200 ); // ȴ + R8_USB2_INT_FG = RB_UIF_DETECT; + s = AnalyzeRootU2Hub(); // ROOT-U2HUB״̬ + + if(s == ERR_USB_CONNECT) + FoundNewU2Dev = 1; +#ifdef DISK_BASE_BUF_LEN + if(CHRV3DiskStatus == DISK_DISCONNECT) + { + return (ERR_USB_DISCON); + } // USB豸Ͽ¼ + if(CHRV3DiskStatus == DISK_CONNECT) + { + return (ERR_USB_CONNECT); + } // USB豸¼ +#else + if(ThisUsb2Dev.DeviceStatus == ROOT_DEV_DISCONNECT) + { + return (ERR_USB_DISCON); + } // USB豸Ͽ¼ + if(ThisUsb2Dev.DeviceStatus == ROOT_DEV_CONNECTED) + { + return (ERR_USB_CONNECT); + } // USB豸¼ +#endif + mDelayuS(200); // ȴ + } + + if(R8_USB2_INT_FG & RB_UIF_TRANSFER) // ¼ + { + if(R8_USB2_INT_ST & RB_UIS_TOG_OK) + { + return (ERR_SUCCESS); + } + r = R8_USB2_INT_ST & MASK_UIS_H_RES; // USB豸Ӧ״̬ + if(r == USB_PID_STALL) + { + return (r | ERR_USB_TRANSFER); + } + if(r == USB_PID_NAK) + { + if(timeout == 0) + { + return (r | ERR_USB_TRANSFER); + } + if(timeout < 0xFFFFFFFF) + timeout--; + --TransRetry; + } + else + switch(endp_pid >> 4) + { + case USB_PID_SETUP: + case USB_PID_OUT: + if(r) + { + return (r | ERR_USB_TRANSFER); + } // dzʱ/,Ӧ + break; // ʱ + case USB_PID_IN: + if(r == USB_PID_DATA0 || r == USB_PID_DATA1) + { // ͬ趪 + } // ͬ + else if(r) + { + return (r | ERR_USB_TRANSFER); + } // dzʱ/,Ӧ + break; // ʱ + default: + return (ERR_USB_UNKNOWN); // ܵ + break; + } + } + else + { // ж,Ӧ÷ + R8_USB2_INT_FG = 0xFF; /* жϱ־ */ + } + mDelayuS(15); + } while(++TransRetry < 3); + return (ERR_USB_TRANSFER); // Ӧʱ +} + +/********************************************************************* + * @fn U2HostCtrlTransfer + * + * @brief ִпƴ,8ֽpSetupReq,DataBufΪѡշ + * + * @param DataBuf - Ҫպͷ,ôDataBufָЧڴź + * @param RetLen - ʵʳɹշܳȱRetLenָֽڱ + * + * @return ERR_USB_BUF_OVER IN״̬׶γ + * ERR_SUCCESS ݽɹ + */ +uint8_t U2HostCtrlTransfer(uint8_t *DataBuf, uint8_t *RetLen) +{ + uint16_t RemLen = 0; + uint8_t s, RxLen, RxCnt, TxCnt; + uint8_t *pBuf; + uint8_t *pLen; + + pBuf = DataBuf; + pLen = RetLen; + mDelayuS(200); + if(pLen) + *pLen = 0; // ʵʳɹշܳ + + R8_U2H_TX_LEN = sizeof(USB_SETUP_REQ); + s = USB2HostTransact(USB_PID_SETUP << 4 | 0x00, 0x00, 200000 / 20); // SETUP׶,200mSʱ + if(s != ERR_SUCCESS) + return (s); + R8_U2H_RX_CTRL = R8_U2H_TX_CTRL = RB_UH_R_TOG | RB_UH_R_AUTO_TOG | RB_UH_T_TOG | RB_UH_T_AUTO_TOG; // ĬDATA1 + R8_U2H_TX_LEN = 0x01; // Ĭݹ״̬׶ΪIN + RemLen = pU2SetupReq->wLength; + if(RemLen && pBuf) // Ҫշ + { + if(pU2SetupReq->bRequestType & USB_REQ_TYP_IN) // + { + while(RemLen) + { + mDelayuS(200); + s = USB2HostTransact(USB_PID_IN << 4 | 0x00, R8_U2H_RX_CTRL, 200000 / 20); // IN + if(s != ERR_SUCCESS) + return (s); + RxLen = R8_USB2_RX_LEN < RemLen ? R8_USB2_RX_LEN : RemLen; + RemLen -= RxLen; + if(pLen) + *pLen += RxLen; // ʵʳɹշܳ + for(RxCnt = 0; RxCnt != RxLen; RxCnt++) + { + *pBuf = pU2HOST_RX_RAM_Addr[RxCnt]; + pBuf++; + } + if(R8_USB2_RX_LEN == 0 || (R8_USB2_RX_LEN & (Usb2DevEndp0Size - 1))) + break; // ̰ + } + R8_U2H_TX_LEN = 0x00; // ״̬׶ΪOUT + } + else // + { + while(RemLen) + { + mDelayuS(200); + R8_U2H_TX_LEN = RemLen >= Usb2DevEndp0Size ? Usb2DevEndp0Size : RemLen; + for(TxCnt = 0; TxCnt != R8_U2H_TX_LEN; TxCnt++) + { + pU2HOST_TX_RAM_Addr[TxCnt] = *pBuf; + pBuf++; + } + s = USB2HostTransact(USB_PID_OUT << 4 | 0x00, R8_U2H_TX_CTRL, 200000 / 20); // OUT + if(s != ERR_SUCCESS) + return (s); + RemLen -= R8_U2H_TX_LEN; + if(pLen) + *pLen += R8_U2H_TX_LEN; // ʵʳɹշܳ + } + // R8_U2H_TX_LEN = 0x01; // ״̬׶ΪIN + } + } + mDelayuS(200); + s = USB2HostTransact((R8_U2H_TX_LEN ? USB_PID_IN << 4 | 0x00 : USB_PID_OUT << 4 | 0x00), RB_UH_R_TOG | RB_UH_T_TOG, 200000 / 20); // STATUS׶ + if(s != ERR_SUCCESS) + return (s); + if(R8_U2H_TX_LEN == 0) + return (ERR_SUCCESS); // ״̬OUT + if(R8_USB2_RX_LEN == 0) + return (ERR_SUCCESS); // ״̬IN,IN״̬ݳ + return (ERR_USB_BUF_OVER); // IN״̬׶δ +} + +/********************************************************************* + * @fn CopyU2SetupReqPkg + * + * @brief ƿƴ + * + * @param pReqPkt - ַ + * + * @return none + */ +void CopyU2SetupReqPkg(const uint8_t *pReqPkt) // ƿƴ +{ + uint8_t i; + for(i = 0; i != sizeof(USB_SETUP_REQ); i++) + { + ((uint8_t *)pU2SetupReq)[i] = *pReqPkt; + pReqPkt++; + } +} + +/********************************************************************* + * @fn CtrlGetU2DeviceDescr + * + * @brief ȡ豸, pHOST_TX_RAM_Addr + * + * @param none + * + * @return ERR_USB_BUF_OVER ȴ + * ERR_SUCCESS ɹ + */ +uint8_t CtrlGetU2DeviceDescr(void) +{ + uint8_t s; + uint8_t len; + + Usb2DevEndp0Size = DEFAULT_ENDP0_SIZE; + CopyU2SetupReqPkg((uint8_t *)SetupGetU2DevDescr); + s = U2HostCtrlTransfer(U2Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + return (s); + Usb2DevEndp0Size = ((PUSB_DEV_DESCR)U2Com_Buffer)->bMaxPacketSize0; // ˵0,Ǽ򻯴,ӦȻȡǰ8ֽںUsbDevEndp0Sizeټ + if(len < ((PUSB_SETUP_REQ)SetupGetU2DevDescr)->wLength) + return (ERR_USB_BUF_OVER); // ȴ + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlGetU2ConfigDescr + * + * @brief ȡ, pHOST_TX_RAM_Addr + * + * @param none + * + * @return ERR_USB_BUF_OVER ȴ + * ERR_SUCCESS ɹ + */ +uint8_t CtrlGetU2ConfigDescr(void) +{ + uint8_t s; + uint8_t len; + + CopyU2SetupReqPkg((uint8_t *)SetupGetU2CfgDescr); + s = U2HostCtrlTransfer(U2Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + return (s); + if(len < ((PUSB_SETUP_REQ)SetupGetU2CfgDescr)->wLength) + return (ERR_USB_BUF_OVER); // سȴ + + len = ((PUSB_CFG_DESCR)U2Com_Buffer)->wTotalLength; + CopyU2SetupReqPkg((uint8_t *)SetupGetU2CfgDescr); + pU2SetupReq->wLength = len; // ܳ + s = U2HostCtrlTransfer(U2Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + return (s); + +#ifdef DISK_BASE_BUF_LEN + if(len > 64) + len = 64; + memcpy(TxBuffer, U2Com_Buffer, len); //U̲ʱҪTxBuffer +#endif + + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlSetUsb2Address + * + * @brief USB豸ַ + * + * @param addr - 豸ַ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsb2Address(uint8_t addr) +{ + uint8_t s; + + CopyU2SetupReqPkg((uint8_t *)SetupSetUsb2Addr); + pU2SetupReq->wValue = addr; // USB豸ַ + s = U2HostCtrlTransfer(NULL, NULL); // ִпƴ + if(s != ERR_SUCCESS) + return (s); + SetHostUsb2Addr(addr); // USBǰUSB豸ַ + mDelaymS(10); // ȴUSB豸ɲ + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlSetUsb2Config + * + * @brief USB豸 + * + * @param cfg - ֵ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsb2Config(uint8_t cfg) +{ + CopyU2SetupReqPkg((uint8_t *)SetupSetUsb2Config); + pU2SetupReq->wValue = cfg; // USB豸 + return (U2HostCtrlTransfer(NULL, NULL)); // ִпƴ +} + +/********************************************************************* + * @fn CtrlClearU2EndpStall + * + * @brief ˵STALL + * + * @param endp - ˵ַ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlClearU2EndpStall(uint8_t endp) +{ + CopyU2SetupReqPkg((uint8_t *)SetupClrU2EndpStall); // ˵Ĵ + pU2SetupReq->wIndex = endp; // ˵ַ + return (U2HostCtrlTransfer(NULL, NULL)); // ִпƴ +} + +/********************************************************************* + * @fn CtrlSetUsb2Intercace + * + * @brief USB豸ӿ + * + * @param cfg - ֵ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsb2Intercace(uint8_t cfg) +{ + CopyU2SetupReqPkg((uint8_t *)SetupSetUsb2Interface); + pU2SetupReq->wValue = cfg; // USB豸 + return (U2HostCtrlTransfer(NULL, NULL)); // ִпƴ +} + +/********************************************************************* + * @fn USB2_HostInit + * + * @brief USBܳʼ + * + * @param none + * + * @return none + */ +void USB2_HostInit(void) +{ + R8_USB2_CTRL = RB_UC_HOST_MODE; + R8_U2HOST_CTRL = 0; + R8_USB2_DEV_AD = 0x00; + + R8_U2H_EP_MOD = RB_UH_EP_TX_EN | RB_UH_EP_RX_EN; + R16_U2H_RX_DMA = (uint16_t)(uint32_t)pU2HOST_RX_RAM_Addr; + R16_U2H_TX_DMA = (uint16_t)(uint32_t)pU2HOST_TX_RAM_Addr; + + R8_U2H_RX_CTRL = 0x00; + R8_U2H_TX_CTRL = 0x00; + R8_USB2_CTRL = RB_UC_HOST_MODE | RB_UC_INT_BUSY | RB_UC_DMA_EN; + R8_U2H_SETUP = RB_UH_SOF_EN; + R8_USB2_INT_FG = 0xFF; + DisableRootU2HubPort(); + R8_USB2_INT_EN = RB_UIE_TRANSFER | RB_UIE_DETECT; + + FoundNewU2Dev = 0; +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostClass.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostClass.c new file mode 100644 index 0000000..55d38fb --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostClass.c @@ -0,0 +1,826 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_usbhost.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" +#if DISK_LIB_ENABLE + #include "CHRV3UFI.H" +#endif + +/* HIDϴ */ +__attribute__((aligned(4))) const uint8_t SetupSetU2HIDIdle[] = {0x21, HID_SET_IDLE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +/* ȡHID豸 */ +__attribute__((aligned(4))) const uint8_t SetupGetU2HIDDevReport[] = {0x81, USB_GET_DESCRIPTOR, 0x00, + USB_DESCR_TYP_REPORT, 0x00, 0x00, 0x41, 0x00}; +/* ȡHUB */ +__attribute__((aligned(4))) const uint8_t SetupGetU2HubDescr[] = {HUB_GET_HUB_DESCRIPTOR, HUB_GET_DESCRIPTOR, + 0x00, USB_DESCR_TYP_HUB, 0x00, 0x00, sizeof(USB_HUB_DESCR), 0x00}; + +__attribute__((aligned(4))) uint8_t U2Com_Buffer[128]; // ûʱ,öʱڴ,öٽҲͨʱ + +/********************************************************************* + * @fn AnalyzeU2HidIntEndp + * + * @brief зHIDж϶˵ĵַ,HubPortIndex0浽ROOTHUBǷֵ򱣴浽HUB½ṹ + * + * @param buf - ݻַ HubPortIndex0ʾHUB0ʾⲿHUBµĶ˿ں + * + * @return ˵ + */ +uint8_t AnalyzeU2HidIntEndp(uint8_t *buf, uint8_t HubPortIndex) +{ + uint8_t i, s, l; + s = 0; + + if(HubPortIndex) + { + memset(DevOnU2HubPort[HubPortIndex - 1].GpVar, 0, sizeof(DevOnU2HubPort[HubPortIndex - 1].GpVar)); // + } + else + { + memset(ThisUsb2Dev.GpVar, 0, sizeof(ThisUsb2Dev.GpVar)); // + } + + for(i = 0; i < ((PUSB_CFG_DESCR)buf)->wTotalLength; i += l) // ж϶˵,ͽӿ + { + if(((PUSB_ENDP_DESCR)(buf + i))->bDescriptorType == USB_DESCR_TYP_ENDP // Ƕ˵ + && (((PUSB_ENDP_DESCR)(buf + i))->bmAttributes & USB_ENDP_TYPE_MASK) == USB_ENDP_TYPE_INTER // ж϶˵ + && (((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_DIR_MASK)) // IN˵ + { // ж϶˵ĵַ,λ7ͬ־λ,0 + if(HubPortIndex) + { + DevOnU2HubPort[HubPortIndex - 1].GpVar[s] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + else + { + ThisUsb2Dev.GpVar[s] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; // ж϶˵ĵַԸҪwMaxPacketSizebInterval + } + PRINT("%02x ", (uint16_t)ThisUsb2Dev.GpVar[s]); + s++; + if(s >= 4) + { + break; //ֻ4˵ + } + } + l = ((PUSB_ENDP_DESCR)(buf + i))->bLength; // ǰ, + if(l > 16) + { + break; + } + } + PRINT("\n"); + return (s); +} + +/********************************************************************* + * @fn AnalyzeU2BulkEndp + * + * @brief ˵,GpVar[0]GpVar[1]ϴ˵㡣GpVar[2]GpVar[3]´˵ + * + * @param buf - ݻַ HubPortIndex0ʾHUB0ʾⲿHUBµĶ˿ں + * + * @return 0 + */ +uint8_t AnalyzeU2BulkEndp(uint8_t *buf, uint8_t HubPortIndex) +{ + uint8_t i, s1, s2, l; + s1 = 0; + s2 = 2; + + if(HubPortIndex) + { + memset(DevOnU2HubPort[HubPortIndex - 1].GpVar, 0, sizeof(DevOnU2HubPort[HubPortIndex - 1].GpVar)); // + } + else + { + memset(ThisUsb2Dev.GpVar, 0, sizeof(ThisUsb2Dev.GpVar)); // + } + + for(i = 0; i < ((PUSB_CFG_DESCR)buf)->wTotalLength; i += l) // ж϶˵,ͽӿ + { + if((((PUSB_ENDP_DESCR)(buf + i))->bDescriptorType == USB_DESCR_TYP_ENDP) // Ƕ˵ + && ((((PUSB_ENDP_DESCR)(buf + i))->bmAttributes & USB_ENDP_TYPE_MASK) == USB_ENDP_TYPE_BULK)) // ж϶˵ + + { + if(HubPortIndex) + { + if(((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_DIR_MASK) + { + DevOnU2HubPort[HubPortIndex - 1].GpVar[s1++] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + else + { + DevOnU2HubPort[HubPortIndex - 1].GpVar[s2++] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + } + else + { + if(((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_DIR_MASK) + { + ThisUsb2Dev.GpVar[s1++] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + else + { + ThisUsb2Dev.GpVar[s2++] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + } + + if(s1 == 2) + { + s1 = 1; + } + if(s2 == 4) + { + s2 = 3; + } + } + l = ((PUSB_ENDP_DESCR)(buf + i))->bLength; // ǰ, + if(l > 16) + { + break; + } + } + return (0); +} + +/********************************************************************* + * @fn InitRootU2Device + * + * @brief ʼָROOT-HUB˿ڵUSB豸 + * + * @param none + * + * @return + */ +uint8_t InitRootU2Device(void) +{ + uint8_t i, s; + uint8_t cfg, dv_cls, if_cls; + + PRINT("Reset U2 host port\n"); + ResetRootU2HubPort(); // ⵽豸,λӦ˿ڵUSB + for(i = 0, s = 0; i < 100; i++) + { // ȴUSB豸λ,100mSʱ + mDelaymS(1); + if(EnableRootU2HubPort() == ERR_SUCCESS) + { // ʹܶ˿ + i = 0; + s++; + if(s > 100) + break; // Ѿȶ100mS + } + } + if(i) + { // λ豸û + DisableRootU2HubPort(); + PRINT("Disable U2 host port because of disconnect\n"); + return (ERR_USB_DISCON); + } + SetUsb2Speed(ThisUsb2Dev.DeviceSpeed); // õǰUSBٶ + + PRINT("GetU2DevDescr: "); + s = CtrlGetU2DeviceDescr(); // ȡ豸 + if(s == ERR_SUCCESS) + { + for(i = 0; i < ((PUSB_SETUP_REQ)SetupGetU2DevDescr)->wLength; i++) + PRINT("x%02X ", (uint16_t)(U2Com_Buffer[i])); + PRINT("\n"); + + ThisUsb2Dev.DeviceVID = ((PUSB_DEV_DESCR)U2Com_Buffer)->idVendor; //VID PIDϢ + ThisUsb2Dev.DevicePID = ((PUSB_DEV_DESCR)U2Com_Buffer)->idProduct; + dv_cls = ((PUSB_DEV_DESCR)U2Com_Buffer)->bDeviceClass; + + s = CtrlSetUsb2Address(((PUSB_SETUP_REQ)SetupSetUsb2Addr)->wValue); + if(s == ERR_SUCCESS) + { + ThisUsb2Dev.DeviceAddress = ((PUSB_SETUP_REQ)SetupSetUsb2Addr)->wValue; // USBַ + + PRINT("GetU2CfgDescr: "); + s = CtrlGetU2ConfigDescr(); + if(s == ERR_SUCCESS) + { + for(i = 0; i < ((PUSB_CFG_DESCR)U2Com_Buffer)->wTotalLength; i++) + { + PRINT("x%02X ", (uint16_t)(U2Com_Buffer[i])); + } + PRINT("\n"); + /* ,ȡ˵/˵ַ/˵С,±endp_addrendp_size */ + cfg = ((PUSB_CFG_DESCR)U2Com_Buffer)->bConfigurationValue; + if_cls = ((PUSB_CFG_DESCR_LONG)U2Com_Buffer)->itf_descr.bInterfaceClass; // ӿ + + if((dv_cls == 0x00) && (if_cls == USB_DEV_CLASS_STORAGE)) + { // USB洢豸,ȷU +#ifdef FOR_ROOT_UDISK_ONLY + CHRV3DiskStatus = DISK_USB_ADDR; + return (ERR_SUCCESS); + } + else + return (ERR_USB_UNSUPPORT); +#else + s = CtrlSetUsb2Config(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + ThisUsb2Dev.DeviceStatus = ROOT_DEV_SUCCESS; + ThisUsb2Dev.DeviceType = USB_DEV_CLASS_STORAGE; + PRINT("U2 USB-Disk Ready\n"); + SetUsb2Speed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + } + else if((dv_cls == 0x00) && (if_cls == USB_DEV_CLASS_PRINTER) && ((PUSB_CFG_DESCR_LONG)U2Com_Buffer)->itf_descr.bInterfaceSubClass == 0x01) + { // Ǵӡ豸 + s = CtrlSetUsb2Config(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + // 豣˵ϢԱUSB + ThisUsb2Dev.DeviceStatus = ROOT_DEV_SUCCESS; + ThisUsb2Dev.DeviceType = USB_DEV_CLASS_PRINTER; + PRINT("U2 USB-Print Ready\n"); + SetUsb2Speed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + } + else if((dv_cls == 0x00) && (if_cls == USB_DEV_CLASS_HID) && ((PUSB_CFG_DESCR_LONG)U2Com_Buffer)->itf_descr.bInterfaceSubClass <= 0x01) + { // HID豸,/ + // зHIDж϶˵ĵַ + s = AnalyzeU2HidIntEndp(U2Com_Buffer, 0); // зHIDж϶˵ĵַ + PRINT("AnalyzeU2HidIntEndp %02x\n", (uint16_t)s); + // ж϶˵ĵַ,λ7ͬ־λ,0 + if_cls = ((PUSB_CFG_DESCR_LONG)U2Com_Buffer)->itf_descr.bInterfaceProtocol; + s = CtrlSetUsb2Config(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + // Set_Idle( ); + // 豣˵ϢԱUSB + ThisUsb2Dev.DeviceStatus = ROOT_DEV_SUCCESS; + if(if_cls == 1) + { + ThisUsb2Dev.DeviceType = DEV_TYPE_KEYBOARD; + // һʼ,豸ָʾLED + PRINT("U2 USB-Keyboard Ready\n"); + SetUsb2Speed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + else if(if_cls == 2) + { + ThisUsb2Dev.DeviceType = DEV_TYPE_MOUSE; + // ΪԺѯ״̬,Ӧ÷,ȡж϶˿ڵĵַ,ȵϢ + PRINT("U2 USB-Mouse Ready\n"); + SetUsb2Speed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + s = ERR_USB_UNSUPPORT; + } + } + else if(dv_cls == USB_DEV_CLASS_HUB) + { // HUB豸, + s = CtrlGetU2HubDescr(); + if(s == ERR_SUCCESS) + { + PRINT("Max Port:%02X ", (((PXUSB_HUB_DESCR)U2Com_Buffer)->bNbrPorts)); + ThisUsb2Dev.GpHUBPortNum = ((PXUSB_HUB_DESCR)U2Com_Buffer)->bNbrPorts; // HUBĶ˿ + if(ThisUsb2Dev.GpHUBPortNum > HUB_MAX_PORTS) + { + ThisUsb2Dev.GpHUBPortNum = HUB_MAX_PORTS; // ΪṹDevOnHubPortʱΪٶÿHUBHUB_MAX_PORTS˿ + } + s = CtrlSetUsb2Config(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + ThisUsb2Dev.DeviceStatus = ROOT_DEV_SUCCESS; + ThisUsb2Dev.DeviceType = USB_DEV_CLASS_HUB; + //豣˵ϢԱUSB,ж϶˵HUB¼֪ͨ,ʹòѯ״̬ƴ + //HUB˿ϵ,ѯ˿״̬,ʼ豸ӵHUB˿,ʼ豸 + for(i = 1; i <= ThisUsb2Dev.GpHUBPortNum; i++) // HUB˿ڶϵ + { + DevOnU2HubPort[i - 1].DeviceStatus = ROOT_DEV_DISCONNECT; // ⲿHUB˿豸״̬ + s = U2HubSetPortFeature(i, HUB_PORT_POWER); + if(s != ERR_SUCCESS) + { + PRINT("Ext-HUB Port_%1d# power on error\n", (uint16_t)i); // ˿ϵʧ + } + } + PRINT("U2 USB-HUB Ready\n"); + SetUsb2Speed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + } + } + else + { // Խһ + s = CtrlSetUsb2Config(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + // 豣˵ϢԱUSB + ThisUsb2Dev.DeviceStatus = ROOT_DEV_SUCCESS; + ThisUsb2Dev.DeviceType = DEV_TYPE_UNKNOW; + SetUsb2Speed(1); // ĬΪȫ + return (ERR_SUCCESS); /* δ֪豸ʼɹ */ + } + } +#endif + } + } + } + + PRINT("InitRootU2Dev Err = %02X\n", (uint16_t)s); +#ifdef FOR_ROOT_UDISK_ONLY + CHRV3DiskStatus = DISK_CONNECT; +#else + ThisUsb2Dev.DeviceStatus = ROOT_DEV_FAILED; +#endif + SetUsb2Speed(1); // ĬΪȫ + return (s); +} + +/********************************************************************* + * @fn InitU2DevOnHub + * + * @brief ʼöⲿHUBĶUSB豸 + * + * @param HubPortIndex - ָⲿHUB + * + * @return + */ +uint8_t InitU2DevOnHub(uint8_t HubPortIndex) +{ + uint8_t i, s, cfg, dv_cls, if_cls; + uint8_t ifc; + PRINT("Init dev @ExtHub-port_%1d ", (uint16_t)HubPortIndex); + if(HubPortIndex == 0) + { + return (ERR_USB_UNKNOWN); + } + SelectU2HubPort(HubPortIndex); // ѡָROOT-HUB˿ڵⲿHUBָ˿,ѡٶ + PRINT("GetDevDescr: "); + s = CtrlGetU2DeviceDescr(); // ȡ豸 + if(s != ERR_SUCCESS) + { + return (s); + } + DevOnU2HubPort[HubPortIndex - 1].DeviceVID = ((uint16_t)((PUSB_DEV_DESCR)U2Com_Buffer)->idVendor); //VID PIDϢ + DevOnU2HubPort[HubPortIndex - 1].DevicePID = ((uint16_t)((PUSB_DEV_DESCR)U2Com_Buffer)->idProduct); + + dv_cls = ((PUSB_DEV_DESCR)U2Com_Buffer)->bDeviceClass; // 豸 + cfg = (1 << 4) + HubPortIndex; // һUSBַ,ַص + s = CtrlSetUsb2Address(cfg); // USB豸ַ + if(s != ERR_SUCCESS) + { + return (s); + } + DevOnU2HubPort[HubPortIndex - 1].DeviceAddress = cfg; // USBַ + PRINT("GetCfgDescr: "); + s = CtrlGetU2ConfigDescr(); // ȡ + if(s != ERR_SUCCESS) + { + return (s); + } + cfg = ((PUSB_CFG_DESCR)U2Com_Buffer)->bConfigurationValue; + for(i = 0; i < ((PUSB_CFG_DESCR)U2Com_Buffer)->wTotalLength; i++) + { + PRINT("x%02X ", (uint16_t)(U2Com_Buffer[i])); + } + PRINT("\n"); + /* ,ȡ˵/˵ַ/˵С,±endp_addrendp_size */ + if_cls = ((PXUSB_CFG_DESCR_LONG)U2Com_Buffer)->itf_descr.bInterfaceClass; // ӿ + if(dv_cls == 0x00 && if_cls == USB_DEV_CLASS_STORAGE) // USB洢豸,ȷU + { + AnalyzeU2BulkEndp(U2Com_Buffer, HubPortIndex); + for(i = 0; i != 4; i++) + { + PRINT("%02x ", (uint16_t)DevOnU2HubPort[HubPortIndex - 1].GpVar[i]); + } + PRINT("\n"); + s = CtrlSetUsb2Config(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + DevOnU2HubPort[HubPortIndex - 1].DeviceStatus = ROOT_DEV_SUCCESS; + DevOnU2HubPort[HubPortIndex - 1].DeviceType = USB_DEV_CLASS_STORAGE; + PRINT("USB-Disk Ready\n"); + SetUsb2Speed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + } + else if((dv_cls == 0x00) && (if_cls == USB_DEV_CLASS_HID) && (((PXUSB_CFG_DESCR_LONG)U2Com_Buffer)->itf_descr.bInterfaceSubClass <= 0x01)) // HID豸,/ + { + ifc = ((PXUSB_CFG_DESCR_LONG)U2Com_Buffer)->cfg_descr.bNumInterfaces; + s = AnalyzeU2HidIntEndp(U2Com_Buffer, HubPortIndex); // зHIDж϶˵ĵַ + PRINT("AnalyzeU2HidIntEndp %02x\n", (uint16_t)s); + if_cls = ((PXUSB_CFG_DESCR_LONG)U2Com_Buffer)->itf_descr.bInterfaceProtocol; + s = CtrlSetUsb2Config(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + for(dv_cls = 0; dv_cls < ifc; dv_cls++) + { + s = CtrlGetU2HIDDeviceReport(dv_cls); //ȡ + if(s == ERR_SUCCESS) + { + for(i = 0; i < 64; i++) + { + PRINT("x%02X ", (uint16_t)(U2Com_Buffer[i])); + } + PRINT("\n"); + } + } + //豣˵ϢԱUSB + DevOnU2HubPort[HubPortIndex - 1].DeviceStatus = ROOT_DEV_SUCCESS; + if(if_cls == 1) + { + DevOnU2HubPort[HubPortIndex - 1].DeviceType = DEV_TYPE_KEYBOARD; + //һʼ,豸ָʾLED + if(ifc > 1) + { + PRINT("USB_DEV_CLASS_HID Ready\n"); + // DevOnU2HubPort[HubPortIndex - 1].DeviceType = USB_DEV_CLASS_HID; //HID豸 + } + PRINT("USB-Keyboard Ready\n"); + SetUsb2Speed(1); // ĬΪȫ + + return (ERR_SUCCESS); + } + else if(if_cls == 2) + { + DevOnU2HubPort[HubPortIndex - 1].DeviceType = DEV_TYPE_MOUSE; + //ΪԺѯ״̬,Ӧ÷,ȡж϶˿ڵĵַ,ȵϢ + if(ifc > 1) + { + PRINT("USB_DEV_CLASS_HID Ready\n"); + // DevOnU2HubPort[HubPortIndex - 1].DeviceType = USB_DEV_CLASS_HID; //HID豸 + } + PRINT("USB-Mouse Ready\n"); + SetUsb2Speed(1); // ĬΪȫ + + return (ERR_SUCCESS); + } + s = ERR_USB_UNSUPPORT; + } + } + else if(dv_cls == USB_DEV_CLASS_HUB) // HUB豸, + { + DevOnU2HubPort[HubPortIndex - 1].DeviceType = USB_DEV_CLASS_HUB; + PRINT("This program don't support Level 2 HUB\n"); // Ҫֶ֧༶HUBοչ + s = U2HubClearPortFeature(i, HUB_PORT_ENABLE); // ֹHUB˿ + if(s != ERR_SUCCESS) + { + return (s); + } + s = ERR_USB_UNSUPPORT; + } + else //豸 + { + AnalyzeU2BulkEndp(U2Com_Buffer, HubPortIndex); //˵ + for(i = 0; i != 4; i++) + { + PRINT("%02x ", (uint16_t)DevOnU2HubPort[HubPortIndex - 1].GpVar[i]); + } + PRINT("\n"); + s = CtrlSetUsb2Config(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + //豣˵ϢԱUSB + DevOnU2HubPort[HubPortIndex - 1].DeviceStatus = ROOT_DEV_SUCCESS; + DevOnU2HubPort[HubPortIndex - 1].DeviceType = dv_cls ? dv_cls : if_cls; + SetUsb2Speed(1); // ĬΪȫ + return (ERR_SUCCESS); //δ֪豸ʼɹ + } + } + PRINT("InitDevOnHub Err = %02X\n", (uint16_t)s); + DevOnU2HubPort[HubPortIndex - 1].DeviceStatus = ROOT_DEV_FAILED; + SetUsb2Speed(1); // ĬΪȫ + return (s); +} + +/********************************************************************* + * @fn EnumU2HubPort + * + * @brief öָROOT-HUB˿ϵⲿHUBĸ˿,˿ӻƳ¼ʼUSB豸 + * + * @param RootHubIndex - ROOT_HUB0ROOT_HUB1 + * + * @return + */ +uint8_t EnumU2HubPort() +{ + uint8_t i, s; + + for(i = 1; i <= ThisUsb2Dev.GpHUBPortNum; i++) // ѯĶ˿Ƿб仯 + { + SelectU2HubPort(0); // ѡָROOT-HUB˿,õǰUSBٶԼ豸USBַ + s = U2HubGetPortStatus(i); // ȡ˿״̬ + if(s != ERR_SUCCESS) + { + return (s); // ǸHUBϿ + } + if(((U2Com_Buffer[0] & (1 << (HUB_PORT_CONNECTION & 0x07))) && (U2Com_Buffer[2] & (1 << (HUB_C_PORT_CONNECTION & 0x07)))) || (U2Com_Buffer[2] == 0x10)) + { // 豸 + DevOnU2HubPort[i - 1].DeviceStatus = ROOT_DEV_CONNECTED; // 豸 + DevOnU2HubPort[i - 1].DeviceAddress = 0x00; + s = U2HubGetPortStatus(i); // ȡ˿״̬ + if(s != ERR_SUCCESS) + { + return (s); // ǸHUBϿ + } + DevOnU2HubPort[i - 1].DeviceSpeed = U2Com_Buffer[1] & (1 << (HUB_PORT_LOW_SPEED & 0x07)) ? 0 : 1; // ٻȫ + if(DevOnU2HubPort[i - 1].DeviceSpeed) + { + PRINT("Found full speed device on port %1d\n", (uint16_t)i); + } + else + { + PRINT("Found low speed device on port %1d\n", (uint16_t)i); + } + mDelaymS(200); // ȴ豸ϵȶ + s = U2HubSetPortFeature(i, HUB_PORT_RESET); // 豸ӵĶ˿ڸλ + if(s != ERR_SUCCESS) + { + return (s); // ǸHUBϿ + } + PRINT("Reset port and then wait in\n"); + do // ѯλ˿,ֱλ,ɺ״̬ʾ + { + mDelaymS(1); + s = U2HubGetPortStatus(i); + if(s != ERR_SUCCESS) + { + return (s); // ǸHUBϿ + } + } while(U2Com_Buffer[0] & (1 << (HUB_PORT_RESET & 0x07))); // ˿ڸλȴ + mDelaymS(100); + s = U2HubClearPortFeature(i, HUB_C_PORT_RESET); // λɱ־ + // s = U2HubSetPortFeature( i, HUB_PORT_ENABLE ); // HUB˿ + s = U2HubClearPortFeature(i, HUB_C_PORT_CONNECTION); // ӻƳ仯־ + if(s != ERR_SUCCESS) + { + return (s); + } + s = U2HubGetPortStatus(i); // ٶȡ״̬,豸Ƿ + if(s != ERR_SUCCESS) + { + return (s); + } + if((U2Com_Buffer[0] & (1 << (HUB_PORT_CONNECTION & 0x07))) == 0) + { + DevOnU2HubPort[i - 1].DeviceStatus = ROOT_DEV_DISCONNECT; // 豸 + } + s = InitU2DevOnHub(i); // ʼUSB豸 + if(s != ERR_SUCCESS) + { + return (s); + } + SetUsb2Speed(1); // ĬΪȫ + } + else if(U2Com_Buffer[2] & (1 << (HUB_C_PORT_ENABLE & 0x07))) // 豸ӳ + { + U2HubClearPortFeature(i, HUB_C_PORT_ENABLE); // Ӵ־ + PRINT("Device on port error\n"); + s = U2HubSetPortFeature(i, HUB_PORT_RESET); // 豸ӵĶ˿ڸλ + if(s != ERR_SUCCESS) + return (s); // ǸHUBϿ + do // ѯλ˿,ֱλ,ɺ״̬ʾ + { + mDelaymS(1); + s = U2HubGetPortStatus(i); + if(s != ERR_SUCCESS) + return (s); // ǸHUBϿ + } while(U2Com_Buffer[0] & (1 << (HUB_PORT_RESET & 0x07))); // ˿ڸλȴ + } + else if((U2Com_Buffer[0] & (1 << (HUB_PORT_CONNECTION & 0x07))) == 0) // 豸ѾϿ + { + if(DevOnU2HubPort[i - 1].DeviceStatus >= ROOT_DEV_CONNECTED) + { + PRINT("Device on port %1d removed\n", (uint16_t)i); + } + DevOnU2HubPort[i - 1].DeviceStatus = ROOT_DEV_DISCONNECT; // 豸 + if(U2Com_Buffer[2] & (1 << (HUB_C_PORT_CONNECTION & 0x07))) + { + U2HubClearPortFeature(i, HUB_C_PORT_CONNECTION); // Ƴ仯־ + } + } + } + return (ERR_SUCCESS); // زɹ +} + +/********************************************************************* + * @fn EnumAllU2HubPort + * + * @brief öROOT-HUB˿ⲿHUBĶUSB豸 + * + * @return + */ +uint8_t EnumAllU2HubPort(void) +{ + uint8_t s; + + if((ThisUsb2Dev.DeviceStatus >= ROOT_DEV_SUCCESS) && (ThisUsb2Dev.DeviceType == USB_DEV_CLASS_HUB)) // HUBöٳɹ + { + SelectU2HubPort(0); // ѡָROOT-HUB˿,õǰUSBٶԼ豸USBַ + s = EnumU2HubPort(); // öָROOT-HUB˿ϵⲿHUBĸ˿,˿ӻƳ¼ + if(s != ERR_SUCCESS) // HUBϿ + { + PRINT("EnumAllHubPort err = %02X\n", (uint16_t)s); + } + SetUsb2Speed(1); // ĬΪȫ + } + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn U2SearchTypeDevice + * + * @brief ROOT-HUBԼⲿHUB˿ָ͵豸ڵĶ˿ں,˿ںΪ0xFFFFδ. + * ȻҲԸUSBijVIDƷPID(Ҫ¼豸VIDPID),Լָ + * + * @param type - 豸 + * + * @return 8λΪROOT-HUB˿ں,8λΪⲿHUBĶ˿ں,8λΪ0豸ֱROOT-HUB˿ + */ +uint16_t U2SearchTypeDevice(uint8_t type) +{ + uint8_t RootHubIndex; //CH554ֻһUSB,RootHubIndex = 0,ֻ迴ֵĵͰλ + uint8_t HubPortIndex; + + RootHubIndex = 0; + if((ThisUsb2Dev.DeviceType == USB_DEV_CLASS_HUB) && (ThisUsb2Dev.DeviceStatus >= ROOT_DEV_SUCCESS)) // ⲿHUBöٳɹ + { + for(HubPortIndex = 1; HubPortIndex <= ThisUsb2Dev.GpHUBPortNum; HubPortIndex++) // ⲿHUBĸ˿ + { + if(DevOnU2HubPort[HubPortIndex - 1].DeviceType == type && DevOnU2HubPort[HubPortIndex - 1].DeviceStatus >= ROOT_DEV_SUCCESS) + { + return (((uint16_t)RootHubIndex << 8) | HubPortIndex); // ƥöٳɹ + } + } + } + if((ThisUsb2Dev.DeviceType == type) && (ThisUsb2Dev.DeviceStatus >= ROOT_DEV_SUCCESS)) + { + return ((uint16_t)RootHubIndex << 8); // ƥöٳɹ,ROOT-HUB˿ + } + + return (0xFFFF); +} + +/********************************************************************* + * @fn U2SETorOFFNumLock + * + * @brief NumLockĵж + * + * @param buf - Ƽֵ + * + * @return + */ +uint8_t U2SETorOFFNumLock(uint8_t *buf) +{ + uint8_t tmp[] = {0x21, 0x09, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00}; + uint8_t len, s; + if((buf[2] == 0x53) & ((buf[0] | buf[1] | buf[3] | buf[4] | buf[5] | buf[6] | buf[7]) == 0)) + { + for(s = 0; s != sizeof(tmp); s++) + { + ((uint8_t *)pU2SetupReq)[s] = tmp[s]; + } + s = U2HostCtrlTransfer(U2Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + } + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlGetU2HIDDeviceReport + * + * @brief ȡHID豸,TxBuffer + * + * @param none + * + * @return + */ +uint8_t CtrlGetU2HIDDeviceReport(uint8_t infc) +{ + uint8_t s; + uint8_t len; + + CopyU2SetupReqPkg((uint8_t *)SetupSetU2HIDIdle); + pU2SetupReq->wIndex = infc; + s = U2HostCtrlTransfer(U2Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + + CopyU2SetupReqPkg((uint8_t *)SetupGetU2HIDDevReport); + pU2SetupReq->wIndex = infc; + s = U2HostCtrlTransfer(U2Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlGetU2HubDescr + * + * @brief ȡHUB,Com_Buffer + * + * @param none + * + * @return + */ +uint8_t CtrlGetU2HubDescr(void) +{ + uint8_t s; + uint8_t len; + + CopyU2SetupReqPkg((uint8_t *)SetupGetU2HubDescr); + s = U2HostCtrlTransfer(U2Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + if(len < ((PUSB_SETUP_REQ)SetupGetU2HubDescr)->wLength) + { + return (ERR_USB_BUF_OVER); // ȴ + } + // if ( len < 4 ) return( ERR_USB_BUF_OVER ); // ȴ + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn U2HubGetPortStatus + * + * @brief ѯHUB˿״̬,Com_Buffer + * + * @param HubPortIndex - ˿ں + * + * @return + */ +uint8_t U2HubGetPortStatus(uint8_t HubPortIndex) +{ + uint8_t s; + uint8_t len; + + pU2SetupReq->bRequestType = HUB_GET_PORT_STATUS; + pU2SetupReq->bRequest = HUB_GET_STATUS; + pU2SetupReq->wValue = 0x0000; + pU2SetupReq->wIndex = 0x0000 | HubPortIndex; + pU2SetupReq->wLength = 0x0004; + s = U2HostCtrlTransfer(U2Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + if(len < 4) + { + return (ERR_USB_BUF_OVER); // ȴ + } + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn U2HubSetPortFeature + * + * @brief HUB˿ + * + * @param HubPortIndex - ˿ں + * @param FeatureSelt - ˿ + * + * @return + */ +uint8_t U2HubSetPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt) +{ + pU2SetupReq->bRequestType = HUB_SET_PORT_FEATURE; + pU2SetupReq->bRequest = HUB_SET_FEATURE; + pU2SetupReq->wValue = 0x0000 | FeatureSelt; + pU2SetupReq->wIndex = 0x0000 | HubPortIndex; + pU2SetupReq->wLength = 0x0000; + return (U2HostCtrlTransfer(NULL, NULL)); // ִпƴ +} + +/********************************************************************* + * @fn U2HubClearPortFeature + * + * @brief HUB˿ + * + * @param HubPortIndex - ˿ں + * @param FeatureSelt - ˿ + * + * @return + */ +uint8_t U2HubClearPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt) +{ + pU2SetupReq->bRequestType = HUB_CLEAR_PORT_FEATURE; + pU2SetupReq->bRequest = HUB_CLEAR_FEATURE; + pU2SetupReq->wValue = 0x0000 | FeatureSelt; + pU2SetupReq->wIndex = 0x0000 | HubPortIndex; + pU2SetupReq->wLength = 0x0000; + return (U2HostCtrlTransfer(NULL, NULL)); // ִпƴ +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usbhostBase.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usbhostBase.c new file mode 100644 index 0000000..27a9d44 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usbhostBase.c @@ -0,0 +1,692 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_usbhost.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" +#if DISK_LIB_ENABLE + #include "CHRV3UFI.H" +#endif + +uint8_t UsbDevEndp0Size; // USB豸Ķ˵0ߴ +uint8_t FoundNewDev; +_RootHubDev ThisUsbDev; //ROOT +_DevOnHubPort DevOnHubPort[HUB_MAX_PORTS]; // ٶ:1ⲿHUB,ÿⲿHUBHUB_MAX_PORTS˿(˲) + +uint8_t *pHOST_RX_RAM_Addr; +uint8_t *pHOST_TX_RAM_Addr; + +/*ȡ豸*/ +__attribute__((aligned(4))) const uint8_t SetupGetDevDescr[] = {USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, + USB_DESCR_TYP_DEVICE, 0x00, 0x00, sizeof(USB_DEV_DESCR), 0x00}; +/*ȡ*/ +__attribute__((aligned(4))) const uint8_t SetupGetCfgDescr[] = {USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, + USB_DESCR_TYP_CONFIG, 0x00, 0x00, 0x04, 0x00}; +/*USBַ*/ +__attribute__((aligned(4))) const uint8_t SetupSetUsbAddr[] = {USB_REQ_TYP_OUT, USB_SET_ADDRESS, USB_DEVICE_ADDR, 0x00, + 0x00, 0x00, 0x00, 0x00}; +/*USB*/ +__attribute__((aligned(4))) const uint8_t SetupSetUsbConfig[] = {USB_REQ_TYP_OUT, USB_SET_CONFIGURATION, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; +/*USBӿ*/ +__attribute__((aligned(4))) const uint8_t SetupSetUsbInterface[] = {USB_REQ_RECIP_INTERF, USB_SET_INTERFACE, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; +/*˵STALL*/ +__attribute__((aligned(4))) const uint8_t SetupClrEndpStall[] = {USB_REQ_TYP_OUT | USB_REQ_RECIP_ENDP, USB_CLEAR_FEATURE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/********************************************************************* + * @fn DisableRootHubPort + * + * @brief رROOT-HUB˿,ʵӲѾԶر,˴ֻһЩṹ״̬ + * + * @param none + * + * @return none + */ +void DisableRootHubPort(void) +{ +#ifdef FOR_ROOT_UDISK_ONLY + CHRV3DiskStatus = DISK_DISCONNECT; +#endif +#ifndef DISK_BASE_BUF_LEN + ThisUsbDev.DeviceStatus = ROOT_DEV_DISCONNECT; + ThisUsbDev.DeviceAddress = 0x00; +#endif +} + +/********************************************************************* + * @fn AnalyzeRootHub + * + * @brief ROOT-HUB״̬,ROOT-HUB˿ڵ豸¼ + * 豸γ,еDisableRootHubPort(),˿ڹر,¼,Ӧ˿ڵ״̬λ + * + * @param none + * + * @return ERR_SUCCESSΪû,ERR_USB_CONNECTΪ⵽,ERR_USB_DISCONΪ⵽Ͽ + */ +uint8_t AnalyzeRootHub(void) +{ + uint8_t s; + + s = ERR_SUCCESS; + + if(R8_USB_MIS_ST & RB_UMS_DEV_ATTACH) + { // 豸 +#ifdef DISK_BASE_BUF_LEN + if(CHRV3DiskStatus == DISK_DISCONNECT +#else + if(ThisUsbDev.DeviceStatus == ROOT_DEV_DISCONNECT // ⵽豸 +#endif + || (R8_UHOST_CTRL & RB_UH_PORT_EN) == 0x00) + { // ⵽豸,δ,˵Ǹղ + DisableRootHubPort(); // رն˿ +#ifdef DISK_BASE_BUF_LEN + CHRV3DiskStatus = DISK_CONNECT; +#else + ThisUsbDev.DeviceSpeed = R8_USB_MIS_ST & RB_UMS_DM_LEVEL ? 0 : 1; + ThisUsbDev.DeviceStatus = ROOT_DEV_CONNECTED; //ӱ־ +#endif + PRINT("USB dev in\n"); + s = ERR_USB_CONNECT; + } + } + +#ifdef DISK_BASE_BUF_LEN + else if(CHRV3DiskStatus >= DISK_CONNECT) + { +#else + else if(ThisUsbDev.DeviceStatus >= ROOT_DEV_CONNECTED) + { //⵽豸γ +#endif + DisableRootHubPort(); // رն˿ + PRINT("USB dev out\n"); + if(s == ERR_SUCCESS) + { + s = ERR_USB_DISCON; + } + } + // R8_USB_INT_FG = RB_UIF_DETECT; // жϱ־ + return (s); +} + +/********************************************************************* + * @fn SetHostUsbAddr + * + * @brief USBǰUSB豸ַ + * + * @param addr - USB豸ַ + * + * @return none + */ +void SetHostUsbAddr(uint8_t addr) +{ + R8_USB_DEV_AD = (R8_USB_DEV_AD & RB_UDA_GP_BIT) | (addr & MASK_USB_ADDR); +} + +/********************************************************************* + * @fn SetUsbSpeed + * + * @brief õǰUSBٶ + * + * @param FullSpeed - USBٶ + * + * @return none + */ +void SetUsbSpeed(uint8_t FullSpeed) +{ +#ifndef DISK_BASE_BUF_LEN + if(FullSpeed) // ȫ + { + R8_USB_CTRL &= ~RB_UC_LOW_SPEED; // ȫ + R8_UH_SETUP &= ~RB_UH_PRE_PID_EN; // ֹPRE PID + } + else + { + R8_USB_CTRL |= RB_UC_LOW_SPEED; // + } +#endif + (void)FullSpeed; +} + +/********************************************************************* + * @fn ResetRootHubPort + * + * @brief ⵽豸,λ,Ϊö豸׼,ΪĬΪȫ + * + * @param none + * + * @return none + */ +void ResetRootHubPort(void) +{ + UsbDevEndp0Size = DEFAULT_ENDP0_SIZE; //USB豸Ķ˵0ߴ + SetHostUsbAddr(0x00); + R8_UHOST_CTRL &= ~RB_UH_PORT_EN; // ص˿ + SetUsbSpeed(1); // ĬΪȫ + R8_UHOST_CTRL = (R8_UHOST_CTRL & ~RB_UH_LOW_SPEED) | RB_UH_BUS_RESET; // ĬΪȫ,ʼλ + mDelaymS(15); // λʱ10mS20mS + R8_UHOST_CTRL = R8_UHOST_CTRL & ~RB_UH_BUS_RESET; // λ + mDelayuS(250); + R8_USB_INT_FG = RB_UIF_DETECT; // жϱ־ +} + +/********************************************************************* + * @fn EnableRootHubPort + * + * @brief ʹROOT-HUB˿,ӦbUH_PORT_EN1˿,豸Ͽܵ·ʧ + * + * @param none + * + * @return ERR_SUCCESSΪ⵽,ERR_USB_DISCONΪ + */ +uint8_t EnableRootHubPort(void) +{ +#ifdef DISK_BASE_BUF_LEN + if(CHRV3DiskStatus < DISK_CONNECT) + CHRV3DiskStatus = DISK_CONNECT; +#else + if(ThisUsbDev.DeviceStatus < ROOT_DEV_CONNECTED) + ThisUsbDev.DeviceStatus = ROOT_DEV_CONNECTED; +#endif + if(R8_USB_MIS_ST & RB_UMS_DEV_ATTACH) + { // 豸 +#ifndef DISK_BASE_BUF_LEN + if((R8_UHOST_CTRL & RB_UH_PORT_EN) == 0x00) + { // δʹ + ThisUsbDev.DeviceSpeed = (R8_USB_MIS_ST & RB_UMS_DM_LEVEL) ? 0 : 1; + if(ThisUsbDev.DeviceSpeed == 0) + { + R8_UHOST_CTRL |= RB_UH_LOW_SPEED; // + } + } +#endif + R8_UHOST_CTRL |= RB_UH_PORT_EN; //ʹHUB˿ + return (ERR_SUCCESS); + } + return (ERR_USB_DISCON); +} + +#ifndef DISK_BASE_BUF_LEN +/********************************************************************* + * @fn SelectHubPort + * + * @brief ѡҪHUB + * + * @param HubPortIndex - ѡָROOT-HUB˿ڵⲿHUBָ˿ + * + * @return None + */ +void SelectHubPort(uint8_t HubPortIndex) +{ + if(HubPortIndex) // ѡָROOT-HUB˿ڵⲿHUBָ˿ + { + SetHostUsbAddr(DevOnHubPort[HubPortIndex - 1].DeviceAddress); // USBǰUSB豸ַ + SetUsbSpeed(DevOnHubPort[HubPortIndex - 1].DeviceSpeed); // õǰUSBٶ + if(DevOnHubPort[HubPortIndex - 1].DeviceSpeed == 0) // ͨⲿHUBUSB豸ͨѶҪǰID + { + R8_UEP1_CTRL |= RB_UH_PRE_PID_EN; // PRE PID + mDelayuS(100); + } + } + else + { + SetHostUsbAddr(ThisUsbDev.DeviceAddress); // USBǰUSB豸ַ + SetUsbSpeed(ThisUsbDev.DeviceSpeed); // USB豸ٶ + } +} +#endif + +/********************************************************************* + * @fn WaitUSB_Interrupt + * + * @brief ȴUSBж + * + * @param none + * + * @return ERR_SUCCESS ݽջ߷ͳɹ,ERR_USB_UNKNOWN ݽջ߷ʧ + */ +uint8_t WaitUSB_Interrupt(void) +{ + uint16_t i; + for(i = WAIT_USB_TOUT_200US; i != 0 && (R8_USB_INT_FG & RB_UIF_TRANSFER) == 0; i--) + { + ; + } + return ((R8_USB_INT_FG & RB_UIF_TRANSFER) ? ERR_SUCCESS : ERR_USB_UNKNOWN); +} + +/********************************************************************* + * @fn USBHostTransact + * + * @brief ,ĿĶ˵ַ/PID,ͬ־,20uSΪλNAKʱ(0,0xFFFF),0ɹ,ʱ/ + * ӳ,ʵӦ,Ϊṩٶ,ӦöԱӳŻ + * + * @param endp_pid - ƺ͵ַ, 4λtoken_pid, 4λǶ˵ַ + * @param tog - ͬ־ + * @param timeout - ʱʱ + * + * @return ERR_USB_UNKNOWN ʱӲ쳣 + * ERR_USB_DISCON 豸Ͽ + * ERR_USB_CONNECT 豸 + * ERR_SUCCESS + */ +uint8_t USBHostTransact(uint8_t endp_pid, uint8_t tog, uint32_t timeout) +{ + uint8_t TransRetry; + + uint8_t s, r; + uint16_t i; + + R8_UH_RX_CTRL = R8_UH_TX_CTRL = tog; + TransRetry = 0; + + do + { + R8_UH_EP_PID = endp_pid; // ָPIDĿĶ˵ + R8_USB_INT_FG = RB_UIF_TRANSFER; + for(i = WAIT_USB_TOUT_200US; i != 0 && (R8_USB_INT_FG & RB_UIF_TRANSFER) == 0; i--) + { + ; + } + R8_UH_EP_PID = 0x00; // ֹͣUSB + if((R8_USB_INT_FG & RB_UIF_TRANSFER) == 0) + { + return (ERR_USB_UNKNOWN); + } + + if(R8_USB_INT_FG & RB_UIF_DETECT) + { // USB豸¼ + // mDelayuS( 200 ); // ȴ + R8_USB_INT_FG = RB_UIF_DETECT; + s = AnalyzeRootHub(); // ROOT-HUB״̬ + + if(s == ERR_USB_CONNECT) + FoundNewDev = 1; +#ifdef DISK_BASE_BUF_LEN + if(CHRV3DiskStatus == DISK_DISCONNECT) + { + return (ERR_USB_DISCON); + } // USB豸Ͽ¼ + if(CHRV3DiskStatus == DISK_CONNECT) + { + return (ERR_USB_CONNECT); + } // USB豸¼ +#else + if(ThisUsbDev.DeviceStatus == ROOT_DEV_DISCONNECT) + { + return (ERR_USB_DISCON); + } // USB豸Ͽ¼ + if(ThisUsbDev.DeviceStatus == ROOT_DEV_CONNECTED) + { + return (ERR_USB_CONNECT); + } // USB豸¼ +#endif + mDelayuS(200); // ȴ + } + + if(R8_USB_INT_FG & RB_UIF_TRANSFER) // ¼ + { + if(R8_USB_INT_ST & RB_UIS_TOG_OK) + { + return (ERR_SUCCESS); + } + r = R8_USB_INT_ST & MASK_UIS_H_RES; // USB豸Ӧ״̬ + if(r == USB_PID_STALL) + { + return (r | ERR_USB_TRANSFER); + } + if(r == USB_PID_NAK) + { + if(timeout == 0) + { + return (r | ERR_USB_TRANSFER); + } + if(timeout < 0xFFFFFFFF) + { + timeout--; + } + --TransRetry; + } + else + switch(endp_pid >> 4) + { + case USB_PID_SETUP: + case USB_PID_OUT: + if(r) + { + return (r | ERR_USB_TRANSFER); + } // dzʱ/,Ӧ + break; // ʱ + case USB_PID_IN: + if(r == USB_PID_DATA0 || r == USB_PID_DATA1) + { // ͬ趪 + } // ͬ + else if(r) + { + return (r | ERR_USB_TRANSFER); + } // dzʱ/,Ӧ + break; // ʱ + default: + return (ERR_USB_UNKNOWN); // ܵ + break; + } + } + else + { // ж,Ӧ÷ + R8_USB_INT_FG = 0xFF; /* жϱ־ */ + } + mDelayuS(15); + } while(++TransRetry < 3); + return (ERR_USB_TRANSFER); // Ӧʱ +} + +/********************************************************************* + * @fn HostCtrlTransfer + * + * @brief ִпƴ,8ֽpSetupReq,DataBufΪѡշ + * + * @param DataBuf - Ҫպͷ,ôDataBufָЧڴź + * @param RetLen - ʵʳɹշܳȱRetLenָֽڱ + * + * @return ERR_USB_BUF_OVER IN״̬׶γ + * ERR_SUCCESS ݽɹ + */ +uint8_t HostCtrlTransfer(uint8_t *DataBuf, uint8_t *RetLen) +{ + uint16_t RemLen = 0; + uint8_t s, RxLen, RxCnt, TxCnt; + uint8_t *pBuf; + uint8_t *pLen; + + pBuf = DataBuf; + pLen = RetLen; + mDelayuS(200); + if(pLen) + { + *pLen = 0; // ʵʳɹշܳ + } + + R8_UH_TX_LEN = sizeof(USB_SETUP_REQ); + s = USBHostTransact(USB_PID_SETUP << 4 | 0x00, 0x00, 200000 / 20); // SETUP׶,200mSʱ + if(s != ERR_SUCCESS) + { + return (s); + } + R8_UH_RX_CTRL = R8_UH_TX_CTRL = RB_UH_R_TOG | RB_UH_R_AUTO_TOG | RB_UH_T_TOG | RB_UH_T_AUTO_TOG; // ĬDATA1 + R8_UH_TX_LEN = 0x01; // Ĭݹ״̬׶ΪIN + RemLen = pSetupReq->wLength; + if(RemLen && pBuf) // Ҫշ + { + if(pSetupReq->bRequestType & USB_REQ_TYP_IN) // + { + while(RemLen) + { + mDelayuS(200); + s = USBHostTransact(USB_PID_IN << 4 | 0x00, R8_UH_RX_CTRL, 200000 / 20); // IN + if(s != ERR_SUCCESS) + { + return (s); + } + RxLen = R8_USB_RX_LEN < RemLen ? R8_USB_RX_LEN : RemLen; + RemLen -= RxLen; + if(pLen) + { + *pLen += RxLen; // ʵʳɹշܳ + } + for(RxCnt = 0; RxCnt != RxLen; RxCnt++) + { + *pBuf = pHOST_RX_RAM_Addr[RxCnt]; + pBuf++; + } + if(R8_USB_RX_LEN == 0 || (R8_USB_RX_LEN & (UsbDevEndp0Size - 1))) + { + break; // ̰ + } + } + R8_UH_TX_LEN = 0x00; // ״̬׶ΪOUT + } + else // + { + while(RemLen) + { + mDelayuS(200); + R8_UH_TX_LEN = RemLen >= UsbDevEndp0Size ? UsbDevEndp0Size : RemLen; + for(TxCnt = 0; TxCnt != R8_UH_TX_LEN; TxCnt++) + { + pHOST_TX_RAM_Addr[TxCnt] = *pBuf; + pBuf++; + } + s = USBHostTransact(USB_PID_OUT << 4 | 0x00, R8_UH_TX_CTRL, 200000 / 20); // OUT + if(s != ERR_SUCCESS) + { + return (s); + } + RemLen -= R8_UH_TX_LEN; + if(pLen) + { + *pLen += R8_UH_TX_LEN; // ʵʳɹշܳ + } + } + // R8_UH_TX_LEN = 0x01; // ״̬׶ΪIN + } + } + mDelayuS(200); + s = USBHostTransact((R8_UH_TX_LEN ? USB_PID_IN << 4 | 0x00 : USB_PID_OUT << 4 | 0x00), RB_UH_R_TOG | RB_UH_T_TOG, 200000 / 20); // STATUS׶ + if(s != ERR_SUCCESS) + { + return (s); + } + if(R8_UH_TX_LEN == 0) + { + return (ERR_SUCCESS); // ״̬OUT + } + if(R8_USB_RX_LEN == 0) + { + return (ERR_SUCCESS); // ״̬IN,IN״̬ݳ + } + return (ERR_USB_BUF_OVER); // IN״̬׶δ +} + +/********************************************************************* + * @fn CopySetupReqPkg + * + * @brief ƿƴ + * + * @param pReqPkt - ַ + * + * @return none + */ +void CopySetupReqPkg(const uint8_t *pReqPkt) // ƿƴ +{ + uint8_t i; + for(i = 0; i != sizeof(USB_SETUP_REQ); i++) + { + ((uint8_t *)pSetupReq)[i] = *pReqPkt; + pReqPkt++; + } +} + +/********************************************************************* + * @fn CtrlGetDeviceDescr + * + * @brief ȡ豸, pHOST_TX_RAM_Addr + * + * @param none + * + * @return ERR_USB_BUF_OVER ȴ + * ERR_SUCCESS ɹ + */ +uint8_t CtrlGetDeviceDescr(void) +{ + uint8_t s; + uint8_t len; + + UsbDevEndp0Size = DEFAULT_ENDP0_SIZE; + CopySetupReqPkg(SetupGetDevDescr); + s = HostCtrlTransfer(Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + UsbDevEndp0Size = ((PUSB_DEV_DESCR)Com_Buffer)->bMaxPacketSize0; // ˵0,Ǽ򻯴,ӦȻȡǰ8ֽںUsbDevEndp0Sizeټ + if(len < ((PUSB_SETUP_REQ)SetupGetDevDescr)->wLength) + { + return (ERR_USB_BUF_OVER); // ȴ + } + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlGetConfigDescr + * + * @brief ȡ, pHOST_TX_RAM_Addr + * + * @param none + * + * @return ERR_USB_BUF_OVER ȴ + * ERR_SUCCESS ɹ + */ +uint8_t CtrlGetConfigDescr(void) +{ + uint8_t s; + uint8_t len; + + CopySetupReqPkg(SetupGetCfgDescr); + s = HostCtrlTransfer(Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + if(len < ((PUSB_SETUP_REQ)SetupGetCfgDescr)->wLength) + { + return (ERR_USB_BUF_OVER); // سȴ + } + + len = ((PUSB_CFG_DESCR)Com_Buffer)->wTotalLength; + CopySetupReqPkg(SetupGetCfgDescr); + pSetupReq->wLength = len; // ܳ + s = HostCtrlTransfer(Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + +#ifdef DISK_BASE_BUF_LEN + if(len > 64) + len = 64; + memcpy(TxBuffer, Com_Buffer, len); //U̲ʱҪTxBuffer +#endif + + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlSetUsbAddress + * + * @brief USB豸ַ + * + * @param addr - 豸ַ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsbAddress(uint8_t addr) +{ + uint8_t s; + + CopySetupReqPkg(SetupSetUsbAddr); + pSetupReq->wValue = addr; // USB豸ַ + s = HostCtrlTransfer(NULL, NULL); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + SetHostUsbAddr(addr); // USBǰUSB豸ַ + mDelaymS(10); // ȴUSB豸ɲ + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlSetUsbConfig + * + * @brief USB豸 + * + * @param cfg - ֵ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsbConfig(uint8_t cfg) +{ + CopySetupReqPkg(SetupSetUsbConfig); + pSetupReq->wValue = cfg; // USB豸 + return (HostCtrlTransfer(NULL, NULL)); // ִпƴ +} + +/********************************************************************* + * @fn CtrlClearEndpStall + * + * @brief ˵STALL + * + * @param endp - ˵ַ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlClearEndpStall(uint8_t endp) +{ + CopySetupReqPkg(SetupClrEndpStall); // ˵Ĵ + pSetupReq->wIndex = endp; // ˵ַ + return (HostCtrlTransfer(NULL, NULL)); // ִпƴ +} + +/********************************************************************* + * @fn CtrlSetUsbIntercace + * + * @brief USB豸ӿ + * + * @param cfg - ֵ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsbIntercace(uint8_t cfg) +{ + CopySetupReqPkg(SetupSetUsbInterface); + pSetupReq->wValue = cfg; // USB豸 + return (HostCtrlTransfer(NULL, NULL)); // ִпƴ +} + +/********************************************************************* + * @fn USB_HostInit + * + * @brief USBܳʼ + * + * @param none + * + * @return none + */ +void USB_HostInit(void) +{ + R8_USB_CTRL = RB_UC_HOST_MODE; + R8_UHOST_CTRL = 0; + R8_USB_DEV_AD = 0x00; + + R8_UH_EP_MOD = RB_UH_EP_TX_EN | RB_UH_EP_RX_EN; + R16_UH_RX_DMA = (uint16_t)(uint32_t)pHOST_RX_RAM_Addr; + R16_UH_TX_DMA = (uint16_t)(uint32_t)pHOST_TX_RAM_Addr; + + R8_UH_RX_CTRL = 0x00; + R8_UH_TX_CTRL = 0x00; + R8_USB_CTRL = RB_UC_HOST_MODE | RB_UC_INT_BUSY | RB_UC_DMA_EN; + R8_UH_SETUP = RB_UH_SOF_EN; + R8_USB_INT_FG = 0xFF; + DisableRootHubPort(); + R8_USB_INT_EN = RB_UIE_TRANSFER | RB_UIE_DETECT; + + FoundNewDev = 0; +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usbhostClass.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usbhostClass.c new file mode 100644 index 0000000..59e28c6 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usbhostClass.c @@ -0,0 +1,832 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH58x_usbhost.c + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#include "CH58x_common.h" +#if DISK_LIB_ENABLE + #include "CHRV3UFI.H" +#endif + +/* HIDϴ */ +__attribute__((aligned(4))) const uint8_t SetupSetHIDIdle[] = {0x21, HID_SET_IDLE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +/* ȡHID豸 */ +__attribute__((aligned(4))) const uint8_t SetupGetHIDDevReport[] = {0x81, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_REPORT, + 0x00, 0x00, 0x41, 0x00}; +/* ȡHUB */ +__attribute__((aligned(4))) const uint8_t SetupGetHubDescr[] = {HUB_GET_HUB_DESCRIPTOR, HUB_GET_DESCRIPTOR, 0x00, + USB_DESCR_TYP_HUB, 0x00, 0x00, sizeof(USB_HUB_DESCR), 0x00}; + +__attribute__((aligned(4))) uint8_t Com_Buffer[128]; // ûʱ,öʱڴ,öٽҲͨʱ + +/********************************************************************* + * @fn AnalyzeHidIntEndp + * + * @brief зHIDж϶˵ĵַ,HubPortIndex0浽ROOTHUBǷֵ򱣴浽HUB½ṹ + * + * @param buf - ݻַ HubPortIndex0ʾHUB0ʾⲿHUBµĶ˿ں + * + * @return ˵ + */ +uint8_t AnalyzeHidIntEndp(uint8_t *buf, uint8_t HubPortIndex) +{ + uint8_t i, s, l; + s = 0; + + if(HubPortIndex) + { + memset(DevOnHubPort[HubPortIndex - 1].GpVar, 0, sizeof(DevOnHubPort[HubPortIndex - 1].GpVar)); // + } + else + { + memset(ThisUsbDev.GpVar, 0, sizeof(ThisUsbDev.GpVar)); // + } + + for(i = 0; i < ((PUSB_CFG_DESCR)buf)->wTotalLength; i += l) // ж϶˵,ͽӿ + { + if(((PUSB_ENDP_DESCR)(buf + i))->bDescriptorType == USB_DESCR_TYP_ENDP // Ƕ˵ + && (((PUSB_ENDP_DESCR)(buf + i))->bmAttributes & USB_ENDP_TYPE_MASK) == USB_ENDP_TYPE_INTER // ж϶˵ + && (((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_DIR_MASK)) // IN˵ + { // ж϶˵ĵַ,λ7ͬ־λ,0 + if(HubPortIndex) + { + DevOnHubPort[HubPortIndex - 1].GpVar[s] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + else + { + ThisUsbDev.GpVar[s] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; // ж϶˵ĵַԸҪwMaxPacketSizebInterval + } + PRINT("%02x ", (uint16_t)ThisUsbDev.GpVar[s]); + s++; + if(s >= 4) + { + break; //ֻ4˵ + } + } + l = ((PUSB_ENDP_DESCR)(buf + i))->bLength; // ǰ, + if(l > 16) + { + break; + } + } + PRINT("\n"); + return (s); +} + +/********************************************************************* + * @fn AnalyzeBulkEndp + * + * @brief ˵,GpVar[0]GpVar[1]ϴ˵㡣GpVar[2]GpVar[3]´˵ + * + * @param buf - ݻַ HubPortIndex0ʾHUB0ʾⲿHUBµĶ˿ں + * + * @return 0 + */ +uint8_t AnalyzeBulkEndp(uint8_t *buf, uint8_t HubPortIndex) +{ + uint8_t i, s1, s2, l; + s1 = 0; + s2 = 2; + + if(HubPortIndex) + { + memset(DevOnHubPort[HubPortIndex - 1].GpVar, 0, sizeof(DevOnHubPort[HubPortIndex - 1].GpVar)); // + } + else + { + memset(ThisUsbDev.GpVar, 0, sizeof(ThisUsbDev.GpVar)); // + } + + for(i = 0; i < ((PUSB_CFG_DESCR)buf)->wTotalLength; i += l) // ж϶˵,ͽӿ + { + if((((PUSB_ENDP_DESCR)(buf + i))->bDescriptorType == USB_DESCR_TYP_ENDP) // Ƕ˵ + && ((((PUSB_ENDP_DESCR)(buf + i))->bmAttributes & USB_ENDP_TYPE_MASK) == USB_ENDP_TYPE_BULK)) // ж϶˵ + + { + if(HubPortIndex) + { + if(((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_DIR_MASK) + { + DevOnHubPort[HubPortIndex - 1].GpVar[s1++] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + else + { + DevOnHubPort[HubPortIndex - 1].GpVar[s2++] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + } + else + { + if(((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_DIR_MASK) + { + ThisUsbDev.GpVar[s1++] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + else + { + ThisUsbDev.GpVar[s2++] = ((PUSB_ENDP_DESCR)(buf + i))->bEndpointAddress & USB_ENDP_ADDR_MASK; + } + } + + if(s1 == 2) + { + s1 = 1; + } + if(s2 == 4) + { + s2 = 3; + } + } + l = ((PUSB_ENDP_DESCR)(buf + i))->bLength; // ǰ, + if(l > 16) + { + break; + } + } + return (0); +} + +/********************************************************************* + * @fn InitRootDevice + * + * @brief ʼָROOT-HUB˿ڵUSB豸 + * + * @param none + * + * @return + */ +uint8_t InitRootDevice(void) +{ + uint8_t i, s; + uint8_t cfg, dv_cls, if_cls; + + PRINT("Reset host port\n"); + ResetRootHubPort(); // ⵽豸,λӦ˿ڵUSB + for(i = 0, s = 0; i < 100; i++) + { // ȴUSB豸λ,100mSʱ + mDelaymS(1); + if(EnableRootHubPort() == ERR_SUCCESS) + { // ʹܶ˿ + i = 0; + s++; + if(s > 100) + { + break; // Ѿȶ100mS + } + } + } + if(i) + { // λ豸û + DisableRootHubPort(); + PRINT("Disable host port because of disconnect\n"); + return (ERR_USB_DISCON); + } + SetUsbSpeed(ThisUsbDev.DeviceSpeed); // õǰUSBٶ + + PRINT("GetDevDescr: "); + s = CtrlGetDeviceDescr(); // ȡ豸 + if(s == ERR_SUCCESS) + { + for(i = 0; i < ((PUSB_SETUP_REQ)SetupGetDevDescr)->wLength; i++) + { + PRINT("x%02X ", (uint16_t)(Com_Buffer[i])); + } + PRINT("\n"); + + ThisUsbDev.DeviceVID = ((PUSB_DEV_DESCR)Com_Buffer)->idVendor; //VID PIDϢ + ThisUsbDev.DevicePID = ((PUSB_DEV_DESCR)Com_Buffer)->idProduct; + dv_cls = ((PUSB_DEV_DESCR)Com_Buffer)->bDeviceClass; + + s = CtrlSetUsbAddress(((PUSB_SETUP_REQ)SetupSetUsbAddr)->wValue); + if(s == ERR_SUCCESS) + { + ThisUsbDev.DeviceAddress = ((PUSB_SETUP_REQ)SetupSetUsbAddr)->wValue; // USBַ + + PRINT("GetCfgDescr: "); + s = CtrlGetConfigDescr(); + if(s == ERR_SUCCESS) + { + for(i = 0; i < ((PUSB_CFG_DESCR)Com_Buffer)->wTotalLength; i++) + { + PRINT("x%02X ", (uint16_t)(Com_Buffer[i])); + } + PRINT("\n"); + /* ,ȡ˵/˵ַ/˵С,±endp_addrendp_size */ + cfg = ((PUSB_CFG_DESCR)Com_Buffer)->bConfigurationValue; + if_cls = ((PUSB_CFG_DESCR_LONG)Com_Buffer)->itf_descr.bInterfaceClass; // ӿ + + if((dv_cls == 0x00) && (if_cls == USB_DEV_CLASS_STORAGE)) + { // USB洢豸,ȷU +#ifdef FOR_ROOT_UDISK_ONLY + CHRV3DiskStatus = DISK_USB_ADDR; + return (ERR_SUCCESS); + } + else + { + return (ERR_USB_UNSUPPORT); + } +#else + s = CtrlSetUsbConfig(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + ThisUsbDev.DeviceStatus = ROOT_DEV_SUCCESS; + ThisUsbDev.DeviceType = USB_DEV_CLASS_STORAGE; + PRINT("USB-Disk Ready\n"); + SetUsbSpeed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + } + else if((dv_cls == 0x00) && (if_cls == USB_DEV_CLASS_PRINTER) && ((PUSB_CFG_DESCR_LONG)Com_Buffer)->itf_descr.bInterfaceSubClass == 0x01) + { // Ǵӡ豸 + s = CtrlSetUsbConfig(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + // 豣˵ϢԱUSB + ThisUsbDev.DeviceStatus = ROOT_DEV_SUCCESS; + ThisUsbDev.DeviceType = USB_DEV_CLASS_PRINTER; + PRINT("USB-Print Ready\n"); + SetUsbSpeed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + } + else if((dv_cls == 0x00) && (if_cls == USB_DEV_CLASS_HID) && ((PUSB_CFG_DESCR_LONG)Com_Buffer)->itf_descr.bInterfaceSubClass <= 0x01) + { // HID豸,/ + // зHIDж϶˵ĵַ + s = AnalyzeHidIntEndp(Com_Buffer, 0); // зHIDж϶˵ĵַ + PRINT("AnalyzeHidIntEndp %02x\n", (uint16_t)s); + // ж϶˵ĵַ,λ7ͬ־λ,0 + if_cls = ((PUSB_CFG_DESCR_LONG)Com_Buffer)->itf_descr.bInterfaceProtocol; + s = CtrlSetUsbConfig(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + // Set_Idle( ); + // 豣˵ϢԱUSB + ThisUsbDev.DeviceStatus = ROOT_DEV_SUCCESS; + if(if_cls == 1) + { + ThisUsbDev.DeviceType = DEV_TYPE_KEYBOARD; + // һʼ,豸ָʾLED + PRINT("USB-Keyboard Ready\n"); + SetUsbSpeed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + else if(if_cls == 2) + { + ThisUsbDev.DeviceType = DEV_TYPE_MOUSE; + // ΪԺѯ״̬,Ӧ÷,ȡж϶˿ڵĵַ,ȵϢ + PRINT("USB-Mouse Ready\n"); + SetUsbSpeed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + s = ERR_USB_UNSUPPORT; + } + } + else if(dv_cls == USB_DEV_CLASS_HUB) + { // HUB豸, + s = CtrlGetHubDescr(); + if(s == ERR_SUCCESS) + { + PRINT("Max Port:%02X ", (((PXUSB_HUB_DESCR)Com_Buffer)->bNbrPorts)); + ThisUsbDev.GpHUBPortNum = ((PXUSB_HUB_DESCR)Com_Buffer)->bNbrPorts; // HUBĶ˿ + if(ThisUsbDev.GpHUBPortNum > HUB_MAX_PORTS) + { + ThisUsbDev.GpHUBPortNum = HUB_MAX_PORTS; // ΪṹDevOnHubPortʱΪٶÿHUBHUB_MAX_PORTS˿ + } + s = CtrlSetUsbConfig(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + ThisUsbDev.DeviceStatus = ROOT_DEV_SUCCESS; + ThisUsbDev.DeviceType = USB_DEV_CLASS_HUB; + //豣˵ϢԱUSB,ж϶˵HUB¼֪ͨ,ʹòѯ״̬ƴ + //HUB˿ϵ,ѯ˿״̬,ʼ豸ӵHUB˿,ʼ豸 + for(i = 1; i <= ThisUsbDev.GpHUBPortNum; i++) // HUB˿ڶϵ + { + DevOnHubPort[i - 1].DeviceStatus = ROOT_DEV_DISCONNECT; // ⲿHUB˿豸״̬ + s = HubSetPortFeature(i, HUB_PORT_POWER); + if(s != ERR_SUCCESS) + { + PRINT("Ext-HUB Port_%1d# power on error\n", (uint16_t)i); // ˿ϵʧ + } + } + PRINT("USB-HUB Ready\n"); + SetUsbSpeed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + } + } + else + { // Խһ + s = CtrlSetUsbConfig(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + // 豣˵ϢԱUSB + ThisUsbDev.DeviceStatus = ROOT_DEV_SUCCESS; + ThisUsbDev.DeviceType = DEV_TYPE_UNKNOW; + SetUsbSpeed(1); // ĬΪȫ + return (ERR_SUCCESS); /* δ֪豸ʼɹ */ + } + } +#endif + } + } + } + + PRINT("InitRootDev Err = %02X\n", (uint16_t)s); +#ifdef FOR_ROOT_UDISK_ONLY + CHRV3DiskStatus = DISK_CONNECT; +#else + ThisUsbDev.DeviceStatus = ROOT_DEV_FAILED; +#endif + SetUsbSpeed(1); // ĬΪȫ + return (s); +} + +/********************************************************************* + * @fn InitDevOnHub + * + * @brief ʼöⲿHUBĶUSB豸 + * + * @param HubPortIndex - ָⲿHUB + * + * @return + */ +uint8_t InitDevOnHub(uint8_t HubPortIndex) +{ + uint8_t i, s, cfg, dv_cls, if_cls; + uint8_t ifc; + PRINT("Init dev @ExtHub-port_%1d ", (uint16_t)HubPortIndex); + if(HubPortIndex == 0) + { + return (ERR_USB_UNKNOWN); + } + SelectHubPort(HubPortIndex); // ѡָROOT-HUB˿ڵⲿHUBָ˿,ѡٶ + PRINT("GetDevDescr: "); + s = CtrlGetDeviceDescr(); // ȡ豸 + if(s != ERR_SUCCESS) + { + return (s); + } + DevOnHubPort[HubPortIndex - 1].DeviceVID = ((uint16_t)((PUSB_DEV_DESCR)Com_Buffer)->idVendor); //VID PIDϢ + DevOnHubPort[HubPortIndex - 1].DevicePID = ((uint16_t)((PUSB_DEV_DESCR)Com_Buffer)->idProduct); + + dv_cls = ((PUSB_DEV_DESCR)Com_Buffer)->bDeviceClass; // 豸 + cfg = (1 << 4) + HubPortIndex; // һUSBַ,ַص + s = CtrlSetUsbAddress(cfg); // USB豸ַ + if(s != ERR_SUCCESS) + { + return (s); + } + DevOnHubPort[HubPortIndex - 1].DeviceAddress = cfg; // USBַ + PRINT("GetCfgDescr: "); + s = CtrlGetConfigDescr(); // ȡ + if(s != ERR_SUCCESS) + { + return (s); + } + cfg = ((PUSB_CFG_DESCR)Com_Buffer)->bConfigurationValue; + for(i = 0; i < ((PUSB_CFG_DESCR)Com_Buffer)->wTotalLength; i++) + { + PRINT("x%02X ", (uint16_t)(Com_Buffer[i])); + } + PRINT("\n"); + /* ,ȡ˵/˵ַ/˵С,±endp_addrendp_size */ + if_cls = ((PXUSB_CFG_DESCR_LONG)Com_Buffer)->itf_descr.bInterfaceClass; // ӿ + if(dv_cls == 0x00 && if_cls == USB_DEV_CLASS_STORAGE) // USB洢豸,ȷU + { + AnalyzeBulkEndp(Com_Buffer, HubPortIndex); + for(i = 0; i != 4; i++) + { + PRINT("%02x ", (uint16_t)DevOnHubPort[HubPortIndex - 1].GpVar[i]); + } + PRINT("\n"); + s = CtrlSetUsbConfig(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + DevOnHubPort[HubPortIndex - 1].DeviceStatus = ROOT_DEV_SUCCESS; + DevOnHubPort[HubPortIndex - 1].DeviceType = USB_DEV_CLASS_STORAGE; + PRINT("USB-Disk Ready\n"); + SetUsbSpeed(1); // ĬΪȫ + return (ERR_SUCCESS); + } + } + else if((dv_cls == 0x00) && (if_cls == USB_DEV_CLASS_HID) && (((PXUSB_CFG_DESCR_LONG)Com_Buffer)->itf_descr.bInterfaceSubClass <= 0x01)) // HID豸,/ + { + ifc = ((PXUSB_CFG_DESCR_LONG)Com_Buffer)->cfg_descr.bNumInterfaces; + s = AnalyzeHidIntEndp(Com_Buffer, HubPortIndex); // зHIDж϶˵ĵַ + PRINT("AnalyzeHidIntEndp %02x\n", (uint16_t)s); + if_cls = ((PXUSB_CFG_DESCR_LONG)Com_Buffer)->itf_descr.bInterfaceProtocol; + s = CtrlSetUsbConfig(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + for(dv_cls = 0; dv_cls < ifc; dv_cls++) + { + s = CtrlGetHIDDeviceReport(dv_cls); //ȡ + if(s == ERR_SUCCESS) + { + for(i = 0; i < 64; i++) + { + PRINT("x%02X ", (uint16_t)(Com_Buffer[i])); + } + PRINT("\n"); + } + } + //豣˵ϢԱUSB + DevOnHubPort[HubPortIndex - 1].DeviceStatus = ROOT_DEV_SUCCESS; + if(if_cls == 1) + { + DevOnHubPort[HubPortIndex - 1].DeviceType = DEV_TYPE_KEYBOARD; + //һʼ,豸ָʾLED + if(ifc > 1) + { + PRINT("USB_DEV_CLASS_HID Ready\n"); + DevOnHubPort[HubPortIndex - 1].DeviceType = USB_DEV_CLASS_HID; //HID豸 + } + PRINT("USB-Keyboard Ready\n"); + SetUsbSpeed(1); // ĬΪȫ + + return (ERR_SUCCESS); + } + else if(if_cls == 2) + { + DevOnHubPort[HubPortIndex - 1].DeviceType = DEV_TYPE_MOUSE; + //ΪԺѯ״̬,Ӧ÷,ȡж϶˿ڵĵַ,ȵϢ + if(ifc > 1) + { + PRINT("USB_DEV_CLASS_HID Ready\n"); + DevOnHubPort[HubPortIndex - 1].DeviceType = USB_DEV_CLASS_HID; //HID豸 + } + PRINT("USB-Mouse Ready\n"); + SetUsbSpeed(1); // ĬΪȫ + + return (ERR_SUCCESS); + } + s = ERR_USB_UNSUPPORT; + } + } + else if(dv_cls == USB_DEV_CLASS_HUB) // HUB豸, + { + DevOnHubPort[HubPortIndex - 1].DeviceType = USB_DEV_CLASS_HUB; + PRINT("This program don't support Level 2 HUB\n"); // Ҫֶ֧༶HUBοչ + s = HubClearPortFeature(i, HUB_PORT_ENABLE); // ֹHUB˿ + if(s != ERR_SUCCESS) + { + return (s); + } + s = ERR_USB_UNSUPPORT; + } + else //豸 + { + AnalyzeBulkEndp(Com_Buffer, HubPortIndex); //˵ + for(i = 0; i != 4; i++) + { + PRINT("%02x ", (uint16_t)DevOnHubPort[HubPortIndex - 1].GpVar[i]); + } + PRINT("\n"); + s = CtrlSetUsbConfig(cfg); // USB豸 + if(s == ERR_SUCCESS) + { + //豣˵ϢԱUSB + DevOnHubPort[HubPortIndex - 1].DeviceStatus = ROOT_DEV_SUCCESS; + DevOnHubPort[HubPortIndex - 1].DeviceType = dv_cls ? dv_cls : if_cls; + SetUsbSpeed(1); // ĬΪȫ + return (ERR_SUCCESS); //δ֪豸ʼɹ + } + } + PRINT("InitDevOnHub Err = %02X\n", (uint16_t)s); + DevOnHubPort[HubPortIndex - 1].DeviceStatus = ROOT_DEV_FAILED; + SetUsbSpeed(1); // ĬΪȫ + return (s); +} + +/********************************************************************* + * @fn EnumHubPort + * + * @brief öָROOT-HUB˿ϵⲿHUBĸ˿,˿ӻƳ¼ʼUSB豸 + * + * @param RootHubIndex - ROOT_HUB0ROOT_HUB1 + * + * @return + */ +uint8_t EnumHubPort() +{ + uint8_t i, s; + + for(i = 1; i <= ThisUsbDev.GpHUBPortNum; i++) // ѯĶ˿Ƿб仯 + { + SelectHubPort(0); // ѡָROOT-HUB˿,õǰUSBٶԼ豸USBַ + s = HubGetPortStatus(i); // ȡ˿״̬ + if(s != ERR_SUCCESS) + { + return (s); // ǸHUBϿ + } + if(((Com_Buffer[0] & (1 << (HUB_PORT_CONNECTION & 0x07))) && (Com_Buffer[2] & (1 << (HUB_C_PORT_CONNECTION & 0x07)))) || (Com_Buffer[2] == 0x10)) + { // 豸 + DevOnHubPort[i - 1].DeviceStatus = ROOT_DEV_CONNECTED; // 豸 + DevOnHubPort[i - 1].DeviceAddress = 0x00; + s = HubGetPortStatus(i); // ȡ˿״̬ + if(s != ERR_SUCCESS) + { + return (s); // ǸHUBϿ + } + DevOnHubPort[i - 1].DeviceSpeed = Com_Buffer[1] & (1 << (HUB_PORT_LOW_SPEED & 0x07)) ? 0 : 1; // ٻȫ + if(DevOnHubPort[i - 1].DeviceSpeed) + { + PRINT("Found full speed device on port %1d\n", (uint16_t)i); + } + else + { + PRINT("Found low speed device on port %1d\n", (uint16_t)i); + } + mDelaymS(200); // ȴ豸ϵȶ + s = HubSetPortFeature(i, HUB_PORT_RESET); // 豸ӵĶ˿ڸλ + if(s != ERR_SUCCESS) + { + return (s); // ǸHUBϿ + } + PRINT("Reset port and then wait in\n"); + do // ѯλ˿,ֱλ,ɺ״̬ʾ + { + mDelaymS(1); + s = HubGetPortStatus(i); + if(s != ERR_SUCCESS) + { + return (s); // ǸHUBϿ + } + } while(Com_Buffer[0] & (1 << (HUB_PORT_RESET & 0x07))); // ˿ڸλȴ + mDelaymS(100); + s = HubClearPortFeature(i, HUB_C_PORT_RESET); // λɱ־ + // s = HubSetPortFeature( i, HUB_PORT_ENABLE ); // HUB˿ + s = HubClearPortFeature(i, HUB_C_PORT_CONNECTION); // ӻƳ仯־ + if(s != ERR_SUCCESS) + { + return (s); + } + s = HubGetPortStatus(i); // ٶȡ״̬,豸Ƿ + if(s != ERR_SUCCESS) + { + return (s); + } + if((Com_Buffer[0] & (1 << (HUB_PORT_CONNECTION & 0x07))) == 0) + { + DevOnHubPort[i - 1].DeviceStatus = ROOT_DEV_DISCONNECT; // 豸 + } + s = InitDevOnHub(i); // ʼUSB豸 + if(s != ERR_SUCCESS) + { + return (s); + } + SetUsbSpeed(1); // ĬΪȫ + } + else if(Com_Buffer[2] & (1 << (HUB_C_PORT_ENABLE & 0x07))) // 豸ӳ + { + HubClearPortFeature(i, HUB_C_PORT_ENABLE); // Ӵ־ + PRINT("Device on port error\n"); + s = HubSetPortFeature(i, HUB_PORT_RESET); // 豸ӵĶ˿ڸλ + if(s != ERR_SUCCESS) + return (s); // ǸHUBϿ + do // ѯλ˿,ֱλ,ɺ״̬ʾ + { + mDelaymS(1); + s = HubGetPortStatus(i); + if(s != ERR_SUCCESS) + return (s); // ǸHUBϿ + } while(Com_Buffer[0] & (1 << (HUB_PORT_RESET & 0x07))); // ˿ڸλȴ + } + else if((Com_Buffer[0] & (1 << (HUB_PORT_CONNECTION & 0x07))) == 0) // 豸ѾϿ + { + if(DevOnHubPort[i - 1].DeviceStatus >= ROOT_DEV_CONNECTED) + { + PRINT("Device on port %1d removed\n", (uint16_t)i); + } + DevOnHubPort[i - 1].DeviceStatus = ROOT_DEV_DISCONNECT; // 豸 + if(Com_Buffer[2] & (1 << (HUB_C_PORT_CONNECTION & 0x07))) + { + HubClearPortFeature(i, HUB_C_PORT_CONNECTION); // Ƴ仯־ + } + } + } + return (ERR_SUCCESS); // زɹ +} + +/********************************************************************* + * @fn EnumAllHubPort + * + * @brief öROOT-HUB˿ⲿHUBĶUSB豸 + * + * @return + */ +uint8_t EnumAllHubPort(void) +{ + uint8_t s; + + if((ThisUsbDev.DeviceStatus >= ROOT_DEV_SUCCESS) && (ThisUsbDev.DeviceType == USB_DEV_CLASS_HUB)) // HUBöٳɹ + { + SelectHubPort(0); // ѡָROOT-HUB˿,õǰUSBٶԼ豸USBַ + s = EnumHubPort(); // öָROOT-HUB˿ϵⲿHUBĸ˿,˿ӻƳ¼ + if(s != ERR_SUCCESS) // HUBϿ + { + PRINT("EnumAllHubPort err = %02X\n", (uint16_t)s); + } + SetUsbSpeed(1); // ĬΪȫ + } + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn SearchTypeDevice + * + * @brief ROOT-HUBԼⲿHUB˿ָ͵豸ڵĶ˿ں,˿ںΪ0xFFFFδ. + * ȻҲԸUSBijVIDƷPID(Ҫ¼豸VIDPID),Լָ + * + * @param type - 豸 + * + * @return 8λΪROOT-HUB˿ں,8λΪⲿHUBĶ˿ں,8λΪ0豸ֱROOT-HUB˿ + */ +uint16_t SearchTypeDevice(uint8_t type) +{ + uint8_t RootHubIndex; //CH554ֻһUSB,RootHubIndex = 0,ֻ迴ֵĵͰλ + uint8_t HubPortIndex; + + RootHubIndex = 0; + if((ThisUsbDev.DeviceType == USB_DEV_CLASS_HUB) && (ThisUsbDev.DeviceStatus >= ROOT_DEV_SUCCESS)) // ⲿHUBöٳɹ + { + for(HubPortIndex = 1; HubPortIndex <= ThisUsbDev.GpHUBPortNum; HubPortIndex++) // ⲿHUBĸ˿ + { + if(DevOnHubPort[HubPortIndex - 1].DeviceType == type && DevOnHubPort[HubPortIndex - 1].DeviceStatus >= ROOT_DEV_SUCCESS) + { + return (((uint16_t)RootHubIndex << 8) | HubPortIndex); // ƥöٳɹ + } + } + } + if((ThisUsbDev.DeviceType == type) && (ThisUsbDev.DeviceStatus >= ROOT_DEV_SUCCESS)) + { + return ((uint16_t)RootHubIndex << 8); // ƥöٳɹ,ROOT-HUB˿ + } + + return (0xFFFF); +} + +/********************************************************************* + * @fn SETorOFFNumLock + * + * @brief NumLockĵж + * + * @param buf - Ƽֵ + * + * @return + */ +uint8_t SETorOFFNumLock(uint8_t *buf) +{ + uint8_t tmp[] = {0x21, 0x09, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00}; + uint8_t len, s; + if((buf[2] == 0x53) & ((buf[0] | buf[1] | buf[3] | buf[4] | buf[5] | buf[6] | buf[7]) == 0)) + { + for(s = 0; s != sizeof(tmp); s++) + { + ((uint8_t *)pSetupReq)[s] = tmp[s]; + } + s = HostCtrlTransfer(Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + } + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlGetHIDDeviceReport + * + * @brief ȡHID豸,TxBuffer + * + * @param none + * + * @return + */ +uint8_t CtrlGetHIDDeviceReport(uint8_t infc) +{ + uint8_t s; + uint8_t len; + + CopySetupReqPkg(SetupSetHIDIdle); + pSetupReq->wIndex = infc; + s = HostCtrlTransfer(Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + + CopySetupReqPkg(SetupGetHIDDevReport); + pSetupReq->wIndex = infc; + s = HostCtrlTransfer(Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn CtrlGetHubDescr + * + * @brief ȡHUB,Com_Buffer + * + * @param none + * + * @return + */ +uint8_t CtrlGetHubDescr(void) +{ + uint8_t s; + uint8_t len; + + CopySetupReqPkg(SetupGetHubDescr); + s = HostCtrlTransfer(Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + if(len < ((PUSB_SETUP_REQ)SetupGetHubDescr)->wLength) + { + return (ERR_USB_BUF_OVER); // ȴ + } + // if ( len < 4 ) return( ERR_USB_BUF_OVER ); // ȴ + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn HubGetPortStatus + * + * @brief ѯHUB˿״̬,Com_Buffer + * + * @param HubPortIndex - ˿ں + * + * @return + */ +uint8_t HubGetPortStatus(uint8_t HubPortIndex) +{ + uint8_t s; + uint8_t len; + + pSetupReq->bRequestType = HUB_GET_PORT_STATUS; + pSetupReq->bRequest = HUB_GET_STATUS; + pSetupReq->wValue = 0x0000; + pSetupReq->wIndex = 0x0000 | HubPortIndex; + pSetupReq->wLength = 0x0004; + s = HostCtrlTransfer(Com_Buffer, &len); // ִпƴ + if(s != ERR_SUCCESS) + { + return (s); + } + if(len < 4) + { + return (ERR_USB_BUF_OVER); // ȴ + } + return (ERR_SUCCESS); +} + +/********************************************************************* + * @fn HubSetPortFeature + * + * @brief HUB˿ + * + * @param HubPortIndex - ˿ں + * @param FeatureSelt - ˿ + * + * @return + */ +uint8_t HubSetPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt) +{ + pSetupReq->bRequestType = HUB_SET_PORT_FEATURE; + pSetupReq->bRequest = HUB_SET_FEATURE; + pSetupReq->wValue = 0x0000 | FeatureSelt; + pSetupReq->wIndex = 0x0000 | HubPortIndex; + pSetupReq->wLength = 0x0000; + return (HostCtrlTransfer(NULL, NULL)); // ִпƴ +} + +/********************************************************************* + * @fn HubClearPortFeature + * + * @brief HUB˿ + * + * @param HubPortIndex - ˿ں + * @param FeatureSelt - ˿ + * + * @return + */ +uint8_t HubClearPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt) +{ + pSetupReq->bRequestType = HUB_CLEAR_PORT_FEATURE; + pSetupReq->bRequest = HUB_CLEAR_FEATURE; + pSetupReq->wValue = 0x0000 | FeatureSelt; + pSetupReq->wIndex = 0x0000 | HubPortIndex; + pSetupReq->wLength = 0x0000; + return (HostCtrlTransfer(NULL, NULL)); // ִпƴ +} diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH583SFR.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH583SFR.h new file mode 100644 index 0000000..05ee89d --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH583SFR.h @@ -0,0 +1,1898 @@ +/* Define for CH583 */ +/* Website: http://wch.cn */ +/* Email: tech@wch.cn */ +/* Author: W.ch 2020.05 */ +/* V0.2 SpecialFunctionRegister */ + +// multi-blocks: __BASE_TYPE__, __CH583SFR_H__, __CH583USBSFR_H__, __USB_TYPE__... + +#ifndef __BASE_TYPE__ +#define __BASE_TYPE__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ********************************************************************************************************************* */ +/* Base types & constants */ + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif + +#ifndef VOID +#define VOID void +#endif +#ifndef CONST +#define CONST const +#endif +#ifndef BOOL +typedef unsigned char BOOL; +#endif +#ifndef BOOLEAN +typedef unsigned char BOOLEAN; +#endif +#ifndef CHAR +typedef char CHAR; +#endif +#ifndef INT8 +typedef char INT8; +#endif +#ifndef INT16 +typedef short INT16; +#endif +#ifndef INT32 +typedef long INT32; +#endif +#ifndef UINT8 +typedef unsigned char UINT8; +#endif +#ifndef UINT16 +typedef unsigned short UINT16; +#endif +#ifndef UINT32 +typedef unsigned long UINT32; +#endif +#ifndef UINT64 +typedef unsigned long long UINT64; +#endif +#ifndef UINT8V +typedef unsigned char volatile UINT8V; +#endif +#ifndef UINT16V +typedef unsigned short volatile UINT16V; +#endif +#ifndef UINT32V +typedef unsigned long volatile UINT32V; +#endif +#ifndef UINT64V +typedef unsigned long long volatile UINT64V; +#endif + +#ifndef PVOID +typedef void *PVOID; +#endif +#ifndef PCHAR +typedef char *PCHAR; +#endif +#ifndef PCHAR +typedef const char *PCCHAR; +#endif +#ifndef PINT8 +typedef char *PINT8; +#endif +#ifndef PINT16 +typedef short *PINT16; +#endif +#ifndef PINT32 +typedef long *PINT32; +#endif +#ifndef PUINT8 +typedef unsigned char *PUINT8; +#endif +#ifndef PUINT16 +typedef unsigned short *PUINT16; +#endif +#ifndef PUINT32 +typedef unsigned long *PUINT32; +#endif +#ifndef PUINT8V +typedef volatile unsigned char *PUINT8V; +#endif +#ifndef PUINT16V +typedef volatile unsigned short *PUINT16V; +#endif +#ifndef PUINT32V +typedef volatile unsigned long *PUINT32V; +#endif +#ifndef PUINT64V +typedef volatile unsigned long long *PUINT64V; +#endif + +/* ********************************************************************************************************************* */ +/* Base macros */ + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/* Calculate the byte offset of a field in a structure of type */ +#define FIELD_OFFSET(Type, Field) ((UINT16)&(((Type *)0)->Field)) + +/* Calculate the size of a field in a structure of type */ +#define FIELD_SIZE(Type, Field) (sizeof(((Type *)0)->Field)) + +/* An expression that yields the type of a field in a struct */ +#define FIELD_TYPE(Type, Field) (((Type *)0)->Field) + +/* Return the number of elements in a statically sized array */ +#define NUMBER_OF(Array) (sizeof(Array)/sizeof((Array)[0])) +#define NUMBER_OF_FIELD(Type, Field) (NUMBER_OF(FIELD_TYPE(Type, Field))) + +#ifdef __cplusplus +} +#endif + +#endif // __BASE_TYPE__ + + +#ifndef __CH583SFR_H__ +#define __CH583SFR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ********************************************************************************************************************* */ + +// Address Space +// CODE: 00000000H - 0007FFFFH 512K +// DATA: 20000000H - 20007FFFH 32KB +// SFR: 40000000H - 4000FFFFH 64KB +// +// SFR: 40000000H - 4000FFFFH, 64KB +// SYS: +1000H - 1BFFH, include base configuration, interrupt, GPIO, etc... +// TMR0: +2000H - 23FFH +// TMR1: +2400H - 27FFH +// TMR2: +2800H - 2BFFH +// TMR3: +2C00H - 2FFFH +// UART0: +3000H - 33FFH +// UART1: +3400H - 37FFH +// UART2: +3800H - 3BFFH +// UART3: +3C00H - 3FFFH +// SPI0: +4000H - 43FFH +// SPI1: +4400H - 47FFH +// I2C: +4800H - 4BFFH +// PWMx: +5000H - 53FFH +// USB: +8000H - 83FFH +// USB2: +8400H - 87FFH +// BLE: +C000H - D3FFH + +// Register Bit Attribute / Bit Access Type +// RF: Read only for Fixed value +// RO: Read Only (internal change) +// RZ: Read only with auto clear Zero +// WO: Write Only (read zero or different) +// WA: Write only under safe Accessing mode (read zero or different) +// WZ: Write only with auto clear Zero +// RW: Read / Write +// RWA: Read / Write under safe Accessing mode +// RW1: Read / Write 1 to Clear + +/* Register name rule: + R32_* for 32 bits register (UINT32,ULONG) + R16_* for 16 bits register (UINT16,USHORT) + R8_* for 8 bits register (UINT8,UCHAR) + RB_* for bit or bit mask of 8 bit register + BA_* for base address point + b* for GPIO bit mask + Others for register address offset */ + +/* ********************************************************************************************************************* */ + +/* System: safe accessing register */ +#define R32_SAFE_ACCESS (*((PUINT32V)0x40001040)) // RW, safe accessing +#define R8_SAFE_ACCESS_SIG (*((PUINT8V)0x40001040)) // WO, safe accessing sign register, must write SAFE_ACCESS_SIG1 then SAFE_ACCESS_SIG2 to enter safe accessing mode +#define RB_SAFE_ACC_MODE 0x03 // RO, current safe accessing mode: 11=safe/unlocked (SAM), other=locked (00..01..10..11) +#define RB_SAFE_ACC_ACT 0x08 // RO, indicate safe accessing status now: 0=locked, read only, 1=safe/unlocked (SAM), write enabled +#define RB_SAFE_ACC_TIMER 0x70 // RO, safe accessing timer bit mask (16*clock number) +#define SAFE_ACCESS_SIG1 0x57 // WO: safe accessing sign value step 1 +#define SAFE_ACCESS_SIG2 0xA8 // WO: safe accessing sign value step 2 +#define SAFE_ACCESS_SIG0 0x00 // WO: safe accessing sign value for disable +#define R8_CHIP_ID (*((PUINT8V)0x40001041)) // RF, chip ID register, always is ID_CH58* +#define R8_SAFE_ACCESS_ID (*((PUINT8V)0x40001042)) // RF, safe accessing ID register, always 0x0C +#define R8_WDOG_COUNT (*((PUINT8V)0x40001043)) // RW, watch-dog count, count by clock frequency Fsys/131072 + +/* System: global configuration register */ +#define R32_GLOBAL_CONFIG (*((PUINT32V)0x40001044)) // RW, global configuration +#define R8_RESET_STATUS (*((PUINT8V)0x40001044)) // RO, reset status +#define RB_RESET_FLAG 0x07 // RO: recent reset flag +#define RST_FLAG_SW 0x00 +#define RST_FLAG_RPOR 0x01 +#define RST_FLAG_WTR 0x02 +#define RST_FLAG_MR 0x03 +//#define RST_FLAG_GPWSM 0x04 // RO, power on reset flag during sleep/shutdown: 0=no power on reset during sleep/shutdown, 1=power on reset occurred during sleep/shutdown +#define RST_FLAG_GPWSM 0x05 +// RB_RESET_FLAG: recent reset flag +// 000 - SR, software reset, by RB_SOFTWARE_RESET=1 @RB_WDOG_RST_EN=0 +// 001 - RPOR, real power on reset +// 010 - WTR, watch-dog timer-out reset +// 011 - MR, external manual reset by RST pin input low +// 101 - GRWSM, global reset by waking under shutdown mode +// 1?? - LRW, power on reset occurred during sleep +#define R8_GLOB_ROM_CFG R8_RESET_STATUS // RWA, flash ROM configuration, SAM +#define RB_ROM_CODE_OFS 0x10 // RWA, code offset address selection in Flash ROM: 0=start address 0x000000, 1=start address 0x040000 +#define RB_ROM_CTRL_EN 0x20 // RWA, enable flash ROM control interface enable: 0=disable access, 1=enable access control register +#define RB_ROM_DATA_WE 0x40 // RWA, enable flash ROM data & code area being erase/write: 0=all writing protect, 1=enable data area program and erase +#define RB_ROM_CODE_WE 0x80 // RWA, enable flash ROM code area being erase/write: 0=code writing protect, 1=enable code area program and erase +#define R8_GLOB_CFG_INFO (*((PUINT8V)0x40001045)) // RO, global configuration information and status +#define RB_CFG_ROM_READ 0x01 // RO, indicate protected status of Flash ROM code and data: 0=reading protect, 1=enable read by external programmer +#define RB_CFG_RESET_EN 0x04 // RO, manual reset input enable status +#define RB_CFG_BOOT_EN 0x08 // RO, boot-loader enable status +#define RB_CFG_DEBUG_EN 0x10 // RO, debug enable status +#define RB_BOOT_LOADER 0x20 // RO, indicate boot loader status: 0=application status (by software reset), 1=boot loader status +#define R8_RST_WDOG_CTRL (*((PUINT8V)0x40001046)) // RWA, reset and watch-dog control, SAM +#define RB_SOFTWARE_RESET 0x01 // WA/WZ, global software reset, high action, auto clear +#define RB_WDOG_RST_EN 0x02 // RWA, enable watch-dog reset if watch-dog timer overflow: 0=as timer only, 1=enable reset if timer overflow +#define RB_WDOG_INT_EN 0x04 // RWA, watch-dog timer overflow interrupt enable: 0=disable, 1=enable +#define RB_WDOG_INT_FLAG 0x10 // RW1, watch-dog timer overflow interrupt flag, cleared by RW1 or reload watch-dog count or __SEV(Send-Event) +#define R8_GLOB_RESET_KEEP (*((PUINT8V)0x40001047)) // RW, value keeper during global reset + +/* System: clock configuration register */ +#define R32_CLOCK_CONFIG (*((PUINT32V)0x40001008)) // RWA, clock configuration, SAM +#define R16_CLK_SYS_CFG (*((PUINT16V)0x40001008)) // RWA, system clock configuration, SAM +#define RB_CLK_PLL_DIV 0x1F // RWA, output clock divider from PLL or CK32M +#define RB_CLK_SYS_MOD 0xC0 // RWA, system clock source mode: 00=divided from 32MHz, 01=divided from PLL-480MHz, 10=directly from 32MHz, 11=directly from 32KHz +#define R8_HFCK_PWR_CTRL (*((PUINT8V)0x4000100A)) // RWA, high frequency clock module power control, SAM +#define RB_CLK_XT32M_PON 0x04 // RWA, external 32MHz oscillator power control: 0=power down, 1-power on +#define RB_CLK_XT32M_KEEP 0x08 // RWA, external 32MHz oscillator power keep under halt mode: 0=auto stop, 1=keep running +#define RB_CLK_PLL_PON 0x10 // RWA, PLL power control: 0=power down, 1-power on +// Fck32k = RB_CLK_OSC32K_XT ? XT_32KHz : RC_32KHz +// Fpll = XT_32MHz * 15 = 480MHz +// Fsys = RB_CLK_SYS_MOD==3 ? Fck32k : ( ( RB_CLK_SYS_MOD[0] ? Fpll : XT_32MHz ) / RB_CLK_PLL_DIV ) +// default: Fsys = XT_32MHz / RB_CLK_PLL_DIV = 32MHz / 5 = 6.4MHz +// range: 32KHz, 2MHz~10MHz, 15MHz~80MHz + +/* System: sleep control register */ +#define R32_SLEEP_CONTROL (*((PUINT32V)0x4000100C)) // RWA, sleep control, SAM +#define R8_SLP_CLK_OFF0 (*((PUINT8V)0x4000100C)) // RWA, sleep clock off control byte 0, SAM +#define RB_SLP_CLK_TMR0 0x01 // RWA, close TMR0 clock +#define RB_SLP_CLK_TMR1 0x02 // RWA, close TMR1 clock +#define RB_SLP_CLK_TMR2 0x04 // RWA, close TMR2 clock +#define RB_SLP_CLK_TMR3 0x08 // RWA, close TMR3 clock +#define RB_SLP_CLK_UART0 0x10 // RWA, close UART0 clock +#define RB_SLP_CLK_UART1 0x20 // RWA, close UART1 clock +#define RB_SLP_CLK_UART2 0x40 // RWA, close UART2 clock +#define RB_SLP_CLK_UART3 0x80 // RWA, close UART3 clock +#define R8_SLP_CLK_OFF1 (*((PUINT8V)0x4000100D)) // RWA, sleep clock off control byte 1, SAM +#define RB_SLP_CLK_SPI0 0x01 // RWA, close SPI0 clock +#define RB_SLP_CLK_SPI1 0x02 // RWA, close SPI1 clock +#define RB_SLP_CLK_PWMX 0x04 // RWA, close PWMx clock +#define RB_SLP_CLK_I2C 0x08 // RWA, close I2C clock +#define RB_SLP_CLK_USB 0x10 // RWA, close USB clock +#define RB_SLP_CLK_USB2 0x20 // RWA, close USB2 clock +#define RB_SLP_CLK_BLE 0x80 // RWA, close BLE clock +#define R8_SLP_WAKE_CTRL (*((PUINT8V)0x4000100E)) // RWA, wake control, SAM +#define RB_SLP_USB_WAKE 0x01 // RWA, enable USB waking +#define RB_SLP_USB2_WAKE 0x02 // RWA, enable USB2 waking +//#define RB_SLP_BLE_WAKE 0x04 // RWA, enable BLE waking +#define RB_SLP_RTC_WAKE 0x08 // RWA, enable RTC waking +#define RB_SLP_GPIO_WAKE 0x10 // RWA, enable GPIO waking +#define RB_SLP_BAT_WAKE 0x20 // RWA, enable BAT waking +#define RB_WAKE_EV_MODE 0x40 // RWA, event wakeup mode: 0=event keep valid for long time, 1=short pulse event +#define R8_SLP_POWER_CTRL (*((PUINT8V)0x4000100F)) // RWA, peripherals power down control, SAM +#define RB_WAKE_DLY_MOD 0x03 // RWA, wakeup delay time selection +// RB_WAKE_DLY_MOD select wakeup delay +// 00: long time, 3590 cycles+TSUHSE +// 01: short time, 520 cycles+TSUHSE +// 10: shorter time, 70 cycles+TSUHSE +// 11: no delay, 8 cycles+TSUHSE +//#define RB_SLP_USB_PWR_DN 0x01 // RWA, enable USB power down +//#define RB_SLP_BLE_PWR_DN 0x04 // RWA, enable BLE power down +#define RB_SLP_CLK_RAMX 0x10 // RWA, close main SRAM clock +#define RB_SLP_CLK_RAM2K 0x20 // RWA, close retention 2KB SRAM clock +#define RB_RAM_RET_LV 0x40 // RWA, SRAM retention voltage selection: 0=normal, 1=low voltage for low power + +/* System: I/O pin configuration register */ +#define R32_PIN_CONFIG (*((PUINT32V)0x40001018)) // RW, I/O pin configuration +#define R16_PIN_ALTERNATE (*((PUINT16V)0x40001018)) // RW, function pin alternate configuration +#define RB_PIN_TMR0 0x01 // RW, TMR0 alternate pin enable: 0=TMR0/PWM0/CAP0 on PA[9], 1=TMR0_/PWM0_/CAP0_ on PB[23] +#define RB_PIN_TMR1 0x02 // RW, TMR1 alternate pin enable: 0=TMR1/PWM1/CAP1 on PA[10], 1=TMR1_/PWM1_/CAP1_ on PB[10] +#define RB_PIN_TMR2 0x04 // RW, TMR2 alternate pin enable: 0=TMR2/PWM2/CAP2 on PA[11], 1=TMR2_/PWM2_/CAP2_ on PB[11] +#define RB_PIN_TMR3 0x08 // RW, TMR3 alternate pin enable: 0=TMR3/PWM3/CAP3 on PA[2], 1=TMR3_/PWM3_/CAP3_ on PB[22] +#define RB_PIN_UART0 0x10 // RW, RXD0/TXD0 alternate pin enable: 0=RXD0/TXD0 on PB[4]/PB[7], 1=RXD0_/TXD0_ on PA[15]/PA[14] +#define RB_PIN_UART1 0x20 // RW, RXD1/TXD1 alternate pin enable: 0=RXD1/TXD1 on PA[8]/PA[9], 1=RXD1_/TXD1_ on PB[12]/PB[13] +#define RB_PIN_UART2 0x40 // RW, RXD2/TXD2 alternate pin enable: 0=RXD2/TXD2 on PA[6]/PA[7], 1=RXD2_/TXD2_ on PB[22]/PB[23] +#define RB_PIN_UART3 0x80 // RW, RXD3/TXD3 alternate pin enable: 0=RXD3/TXD3 on PA[4]/PA[5], 1=RXD3_/TXD3_ on PB[20]/PB[21] +#define RB_PIN_SPI0 0x100 // RW, SCS/SCK0/MOSI/MISO alternate pin enable: 0=SCS/SCK0/MOSI/MISO on PA[12]/PA[13]/PA[14]/PA[15], 1=SCS_/SCK0_/MOSI_/MISO_ on PB[12]/PB[13]/PB[14]/PB[15] +#define RB_PIN_PWMX 0x400 // RW, PWM4/PWM5/PWM7/PWM8/PWM9 alternate pin enable: 0=PWM4/5/7/8/9 on PA[12]/PA[13]/PB[4]/PB[6]/PB[7], 1=PWM4/5/7/8/9 on PA[6]/PA[7]/PB[1]/PB[2]/P[3] +#define RB_PIN_I2C 0x800 // RW, SCL/SDA alternate pin enable: 0=SCL/SDA on PB[13]/PB[12], 1=SCL_/SDA_ on PB[21]/PB[20] +#define RB_PIN_MODEM 0x1000 // RW, DSR/DTR alternate pin enable: 0=DSR/DTR on PB[1]/PB[5], 1=DSR_/DTR_ on PB[14]/PB[15] +#define RB_PIN_INTX 0x2000 // RW, interrupt INT24/INT25 alternate pin enable: 0=INT24/INT25 on PB[8]/PB[9], 1=INT24_/INT25_ on PB[22]/PB[23] +#define RB_PIN_U0_INV 0x4000 // RW, RXD0/RXD0_/TXD0/TXD0_ invert input/output enable: 0=normal input/output, 1=RXD invert input, TXD invert output +#define RB_RF_ANT_SW_EN 0x8000 // RW, RF antenna switch control output enable: 0=disable output, 1=output on PB[16]/PB[17]/PB[18]/PB[19]/PB[20]/PB[21] +#define R16_PIN_ANALOG_IE (*((PUINT16V)0x4000101A)) // RW, analog pin enable and digital input disable +#define RB_PIN_ADC8_9_IE 0x01 // RW, ADC/TouchKey channel 9/8 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_ADC6_7_IE 0x02 // RW, ADC/TouchKey channel 7/6 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_ADC10_IE 0x04 // RW, ADC/TouchKey channel 10 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_ADC11_IE 0x08 // RW, ADC/TouchKey channel 11 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_USB2_DP_PU 0x10 // RW, USB2 UDP internal pullup resistance enable: 0=enable/disable by RB_UC_DEV_PU_EN, 1=enable pullup, replace RB_UC_DEV_PU_EN under sleep mode +#define RB_PIN_USB2_IE 0x20 // RW, USB2 analog I/O enable: 0=analog I/O disable, 1=analog I/O enable +#define RB_PIN_USB_DP_PU 0x40 // RW, USB UDP internal pullup resistance enable: 0=enable/disable by RB_UC_DEV_PU_EN, 1=enable pullup, replace RB_UC_DEV_PU_EN under sleep mode +#define RB_PIN_USB_IE 0x80 // RW, USB analog I/O enable: 0=analog I/O disable, 1=analog I/O enable +#define RB_PIN_ADC0_IE 0x0200 // RW, ADC/TouchKey channel 0 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_ADC1_IE 0x0400 // RW, ADC/TouchKey channel 1 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_ADC12_IE 0x0800 // RW, ADC/TouchKey channel 12 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_ADC13_IE 0x1000 // RW, ADC/TouchKey channel 13 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_XT32K_IE 0x2000 // RW, external 32KHz oscillator digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_ADC2_3_IE 0x4000 // RW, ADC/TouchKey channel 2/3 digital input disable: 0=digital input enable, 1=digital input disable +#define RB_PIN_ADC4_5_IE 0x8000 // RW, ADC/TouchKey channel 4/5 digital input disable: 0=digital input enable, 1=digital input disable + +/* System: power management register */ +#define R32_POWER_MANAG (*((PUINT32V)0x40001020)) // RWA, power management register, SAM +#define R16_POWER_PLAN (*((PUINT16V)0x40001020)) // RWA, power plan before sleep instruction, SAM +#define RB_PWR_XROM 0x01 // RWA, power for flash ROM +#define RB_PWR_RAM2K 0x02 // RWA, power for retention 2KB SRAM +#define RB_PWR_CORE 0x04 // RWA, power retention for core and base peripherals +#define RB_PWR_EXTEND 0x08 // RWA, power retention for USB and BLE +#define RB_PWR_RAM30K 0x10 // RWA, power for main SRAM +#define RB_PWR_SYS_EN 0x80 // RWA, power for system +//#define RB_PWR_LDO_EN 0x0100 // RWA, LDO enable +#define RB_PWR_DCDC_EN 0x0200 // RWA, DC/DC converter enable: 0=DC/DC disable and bypass, 1=DC/DC enable +#define RB_PWR_DCDC_PRE 0x0400 // RWA, DC/DC converter pre-enable +#define RB_PWR_PLAN_EN 0x8000 // RWA/WZ, power plan enable, auto clear after sleep executed +#define RB_PWR_MUST_0010 0x1000 // RWA, must write 0010 +#define R16_AUX_POWER_ADJ (*((PUINT8V)0x40001022)) // RWA, aux power adjust control, SAM +#define RB_ULPLDO_ADJ 0x0007 // RWA, Ultra-Low-Power LDO voltage adjust +#define RB_DCDC_CHARGE 0x0080 // RWA, DC/DC aux charge enable + +/* System: battery detector register */ +#define R32_BATTERY_CTRL (*((PUINT32V)0x40001024)) // RWA, battery voltage detector, SAM +#define R8_BAT_DET_CTRL (*((PUINT8V)0x40001024)) // RWA, battery voltage detector control, SAM +#define RB_BAT_DET_EN 0x01 // RWA, battery voltage detector enable if RB_BAT_MON_EN=0 +#define RB_BAT_LOW_VTHX 0x01 // RWA, select monitor threshold voltage if RB_BAT_MON_EN=1 +#define RB_BAT_MON_EN 0x02 // RWA, battery voltage monitor enable under sleep mode +#define RB_BAT_LOWER_IE 0x04 // RWA, interrupt enable for battery lower voltage +#define RB_BAT_LOW_IE 0x08 // RWA, interrupt enable for battery low voltage +// request NMI interrupt if both RB_BAT_LOWER_IE and RB_BAT_LOW_IE enabled +#define R8_BAT_DET_CFG (*((PUINT8V)0x40001025)) // RWA, battery voltage detector configuration, SAM +#define RB_BAT_LOW_VTH 0x03 // RWA, select detector/monitor threshold voltage of battery voltage low +#define R8_BAT_STATUS (*((PUINT8V)0x40001026)) // RO, battery status +#define RB_BAT_STAT_LOWER 0x01 // RO, battery lower voltage status for detector, high action +#define RB_BAT_STAT_LOW 0x02 // RO, battery low voltage status for detector/monitor, high action + +/* System: 32KHz oscillator control register */ +#define R32_OSC32K_CTRL (*((PUINT32V)0x4000102C)) // RWA, 32KHz oscillator control, SAM +#define R16_INT32K_TUNE (*((PUINT16V)0x4000102C)) // RWA, internal 32KHz oscillator tune control, SAM +#define RB_INT32K_TUNE 0x1FFF // RWA, internal 32KHz oscillator frequency tune +#define R8_XT32K_TUNE (*((PUINT8V)0x4000102E)) // RWA, external 32KHz oscillator tune control, SAM +#define RB_XT32K_I_TUNE 0x03 // RWA, external 32KHz oscillator current tune: 00=75% current, 01=standard current, 10=150% current, 11=200% current for startup +#define RB_XT32K_C_LOAD 0xF0 // RWA, external 32KHz oscillator load capacitor tune: Cap = RB_XT32K_C_LOAD + 12pF +#define R8_CK32K_CONFIG (*((PUINT8V)0x4000102F)) // RWA, 32KHz oscillator configure +#define RB_CLK_XT32K_PON 0x01 // RWA, external 32KHz oscillator power on +#define RB_CLK_INT32K_PON 0x02 // RWA, internal 32KHz oscillator power on +#define RB_CLK_OSC32K_XT 0x04 // RWA, 32KHz oscillator source selection: 0=RC, 1=XT +#define RB_CLK_OSC32K_FILT 0x08 // RWA, internal 32KHz oscillator low noise mode disable: 0=enable, 1=disable +#define RB_32K_CLK_PIN 0x80 // RO, 32KHz oscillator clock pin status + +/* System: real-time clock register */ +#define R32_RTC_CTRL (*((PUINT32V)0x40001030)) // RWA, RTC control, SAM +#define R8_RTC_FLAG_CTRL (*((PUINT8V)0x40001030)) // RW, RTC flag and clear control +#define RB_RTC_TMR_CLR 0x10 // RW, set 1 to clear RTC timer action flag, auto clear +#define RB_RTC_TRIG_CLR 0x20 // RW, set 1 to clear RTC trigger action flag, auto clear +#define RB_RTC_TMR_FLAG 0x40 // RO, RTC timer action flag +#define RB_RTC_TRIG_FLAG 0x80 // RO, RTC trigger action flag +#define R8_RTC_MODE_CTRL (*((PUINT8V)0x40001031)) // RWA, RTC mode control, SAM +#define RB_RTC_TMR_MODE 0x07 // RWA, RTC timer mode: 000=0.125S, 001=0.25S, 010=0.5S, 011=1S, 100=2S, 101=4S, 110=8S, 111=16S +#define RB_RTC_IGNORE_B0 0x08 // RWA, force ignore bit0 for trigger mode: 0=compare bit0, 1=ignore bit0 +#define RB_RTC_TMR_EN 0x10 // RWA, RTC timer mode enable +#define RB_RTC_TRIG_EN 0x20 // RWA, RTC trigger mode enable +#define RB_RTC_LOAD_LO 0x40 // RWA, set 1 to load RTC count low word R32_RTC_CNT_32K, auto clear after loaded +#define RB_RTC_LOAD_HI 0x80 // RWA, set 1 to load RTC count high word R32_RTC_CNT_DAY, auto clear after loaded +#define R32_RTC_TRIG (*((PUINT32V)0x40001034)) // RWA, RTC trigger value, SAM +#define R32_RTC_CNT_32K (*((PUINT32V)0x40001038)) // RO, RTC count based 32KHz +#define R16_RTC_CNT_32K (*((PUINT16V)0x40001038)) // RO, RTC count based 32KHz +#define R16_RTC_CNT_2S (*((PUINT16V)0x4000103A)) // RO, RTC count based 2 second +#define R32_RTC_CNT_DAY (*((PUINT32V)0x4000103C)) // RO, RTC count based one day, only low 14 bit + +/*System: Miscellaneous Control register */ +#define R32_MISC_CTRL (*((PUINT32V)0x40001048)) // RWA, miscellaneous control register +#define R8_PLL_CONFIG (*((PUINT8V)0x4000104B)) // RWA, PLL configuration control, SAM +#define RB_FLASH_IO_MOD 0x80 // RWA, flash ROM interface mode, SAM +#define RB_PLL_CFG_DAT 0x7F // RWA, PLL configuration control, SAM + +/* System: 32MHz oscillator control register */ +#define R32_OSC32M_CTRL (*((PUINT32V)0x4000104C)) // RWA, 32MHz oscillator control, SAM +#define R8_XT32M_TUNE (*((PUINT8V)0x4000104E)) // RWA, external 32MHz oscillator tune control, SAM +#define RB_XT32M_I_BIAS 0x03 // RWA, external 32MHz oscillator bias current tune: 00=75% current, 01=standard current, 10=125% current, 11=150% current +#define RB_XT32M_C_LOAD 0x70 // RWA, external 32MHz oscillator load capacitor tune: Cap = RB_XT32M_C_LOAD * 2 + 10pF + +/* System: oscillator frequency calibration register */ +#define R32_OSC_CALIB (*((PUINT32V)0x40001050)) // RWA, oscillator frequency calibration, SAM +#define R16_OSC_CAL_CNT (*((PUINT16V)0x40001050)) // RO, system clock count value for 32KHz multi-cycles +#define RB_OSC_CAL_CNT 0x3FFF // RO, system clock count value for 32KHz multi-cycles +#define RB_OSC_CAL_OV_CLR 0x4000 // RW1, indicate R8_OSC_CAL_OV_CNT not zero, set 1 to clear R8_OSC_CAL_OV_CNT +#define RB_OSC_CAL_IF 0x8000 // RW1, interrupt flag for oscillator capture end, set 1 to clear +#define R8_OSC_CAL_OV_CNT (*((PUINT8V)0x40001052)) // RO, oscillator frequency calibration overflow times +#define R8_OSC_CAL_CTRL (*((PUINT8V)0x40001053)) // RWA, oscillator frequency calibration control, SAM +#define RB_OSC_CNT_TOTAL 0x07 // RWA, total cycles mode for oscillator capture +// RB_OSC_CNT_TOTAL: select total cycles for oscillator capture +// 000: 1 +// 001: 2 +// 010: 4 +// 011: 32 +// 100: 64 +// 101: 128 +// 110: 1024 +// 111: 2047 +#define RB_OSC_CNT_HALT 0x08 // RO, calibration counter halt status: 0=counting, 1=halt for reading count value +#define RB_OSC_CAL_IE 0x10 // RWA, interrupt enable for oscillator capture end +#define RB_OSC_CNT_EN 0x20 // RWA, calibration counter enable +#define RB_OSC_CNT_END 0x40 // RWA, select oscillator capture end mode: 0=normal, 1=append 2 cycles + +/* System: ADC and Touch-key register */ +#define R32_ADC_CTRL (*((PUINT32V)0x40001058)) // RW, ADC control +#define R8_ADC_CHANNEL (*((PUINT8V)0x40001058)) // RW, ADC input channel selection +#define RB_ADC_CH_INX 0x0F // RW, ADC input channel index +#define R8_ADC_CFG (*((PUINT8V)0x40001059)) // RW, ADC configure +#define RB_ADC_POWER_ON 0x01 // RW, ADC power control: 0=power down, 1=power on +#define RB_ADC_BUF_EN 0x02 // RW, ADC input buffer enable +#define RB_ADC_DIFF_EN 0x04 // RW, ADC input channel mode: 0=single-end, 1=differnetial +#define RB_ADC_OFS_TEST 0x08 // RW, enable ADC offset test mode: 0=normal mode, 1=short to test offset +#define RB_ADC_PGA_GAIN 0x30 // RW, set ADC input PGA gain: 00=-12dB, 01=-6dB, 10=0dB, 11=6dB +#define RB_ADC_CLK_DIV 0xC0 // RW, select ADC clock frequency: 00=3.2MHz, 01=8MHz, 10=5.33MHz, 11=4MHz +#define R8_ADC_CONVERT (*((PUINT8V)0x4000105A)) // RW, ADC convert control +#define RB_ADC_START 0x01 // RW, ADC convert start control: 0=stop ADC convert, 1=start an ADC convert, auto clear +#define RB_ADC_EOC_X 0x80 // RO, end of ADC conversion flag +#define R8_TEM_SENSOR (*((PUINT8V)0x4000105B)) // RW, temperature sensor control +#define RB_TEM_SEN_PWR_ON 0x80 // RW, temperature sensor power control: 0=power down, 1=power on +#define R32_ADC_DATA (*((PUINT32V)0x4000105C)) // RO, ADC data and status +#define R16_ADC_DATA (*((PUINT16V)0x4000105C)) // RO, ADC data +#define RB_ADC_DATA 0x0FFF // RO, ADC conversion data +#define R8_ADC_INT_FLAG (*((PUINT8V)0x4000105E)) // RO, ADC interrupt flag register +#define RB_ADC_IF_EOC 0x80 // RO, ADC conversion interrupt flag: 0=free or converting, 1=end of conversion, interrupt action, auto ADC or write R8_ADC_CONVERT or write R8_TKEY_CONVERT to clear flag +#define R32_TKEY_CTRL (*((PUINT8V)0x40001054)) // RW, Touchkey control +#define R8_TKEY_COUNT (*((PUINT8V)0x40001054)) // RW, Touchkey charge and discharge count +#define RB_TKEY_CHARG_CNT 0x1F // RW, Touchkey charge count +#define RB_TKEY_DISCH_CNT 0xE0 // RW, Touchkey discharge count +#define R8_TKEY_CONVERT (*((PUINT8V)0x40001056)) // RW, Touchkey convert control +#define RB_TKEY_START 0x01 // RW, Touchkey convert start control: 0=stop Touchkey convert, 1=start a Touchkey convert, auto clear +#define R8_TKEY_CFG (*((PUINT8V)0x40001057)) // RW, Touchkey configure +#define RB_TKEY_PWR_ON 0x01 // RW, Touchkey power on: 0=power down, 1=power on +#define RB_TKEY_CURRENT 0x02 // RW, Touchkey charge current selection: 0=35uA, 1=70uA +#define RB_TKEY_DRV_EN 0x04 // RW, Touchkey drive shield enable +#define RB_TKEY_PGA_ADJ 0x08 // RW, ADC input PGA speed selection: 0=slow, 1=fast +#define R32_ADC_DMA_CTRL (*((PUINT32V)0x40001060)) // RW, ADC DMA control +#define R8_ADC_CTRL_DMA (*((PUINT8V)0x40001061)) // RW, ADC DMA control +#define RB_ADC_DMA_ENABLE 0x01 // RW, ADC DMA enable +#define RB_ADC_DMA_LOOP 0x04 // RW, ADC DMA address loop enable +#define RB_ADC_IE_DMA_END 0x08 // RW, enable interrupt for ADC DMA completion +#define RB_ADC_IE_EOC 0x10 // RW, enable interrupt for end of ADC conversion +#define RB_ADC_CONT_EN 0x40 // RW, enable contineous conversion ADC +#define RB_ADC_AUTO_EN 0x80 // RW, enable auto continuing ADC for DMA +#define R8_ADC_DMA_IF (*((PUINT8V)0x40001062)) // RW1, ADC interrupt flag +#define RB_ADC_IF_DMA_END 0x08 // RW1, interrupt flag for ADC DMA completion +#define RB_ADC_IF_END_ADC 0x10 // RW1, interrupt flag for end of ADC conversion, DMA for auto ADC or write R8_ADC_CONVERT to clear flag +#define R8_ADC_AUTO_CYCLE (*((PUINT8V)0x40001063)) // RW, auto ADC cycle value, unit is 16 Fsys +#define R32_ADC_DMA_NOW (*((PUINT32V)0x40001064)) // RW, ADC DMA current address +#define R16_ADC_DMA_NOW (*((PUINT16V)0x40001064)) // RW, ADC DMA current address +#define R32_ADC_DMA_BEG (*((PUINT32V)0x40001068)) // RW, ADC DMA begin address +#define R16_ADC_DMA_BEG (*((PUINT16V)0x40001068)) // RW, ADC DMA begin address +#define R32_ADC_DMA_END (*((PUINT32V)0x4000106C)) // RW, ADC DMA end address +#define R16_ADC_DMA_END (*((PUINT16V)0x4000106C)) // RW, ADC DMA end address + +/* System: Flash ROM control register */ +#define R32_FLASH_DATA (*((PUINT32V)0x40001800)) // RO/WO, flash ROM data +#define R32_FLASH_CONTROL (*((PUINT32V)0x40001804)) // RW, flash ROM control +#define R8_FLASH_DATA (*((PUINT8V)0x40001804)) // RO/WO, flash ROM data buffer +#define R8_FLASH_CTRL (*((PUINT8V)0x40001806)) // RW, flash ROM access control +#define R8_FLASH_CFG (*((PUINT8V)0x40001807)) // RW, flash ROM access config, SAM + +/* System: GPIO interrupt control register */ +#define R32_GPIO_INT_EN (*((PUINT32V)0x40001090)) // RW, GPIO interrupt enable +#define R16_PA_INT_EN (*((PUINT16V)0x40001090)) // RW, GPIO PA interrupt enable +#define R16_PB_INT_EN (*((PUINT16V)0x40001092)) // RW, GPIO PB interrupt enable +#define R32_GPIO_INT_MODE (*((PUINT32V)0x40001094)) // RW, GPIO interrupt mode: 0=level action, 1=edge action +#define R16_PA_INT_MODE (*((PUINT16V)0x40001094)) // RW, GPIO PA interrupt mode: 0=level action, 1=edge action +#define R16_PB_INT_MODE (*((PUINT16V)0x40001096)) // RW, GPIO PB interrupt mode: 0=level action, 1=edge action +#define R32_GPIO_INT_IF (*((PUINT32V)0x4000109C)) // RW1, GPIO interrupt flag +#define R16_PA_INT_IF (*((PUINT16V)0x4000109C)) // RW1, GPIO PA interrupt flag +#define R16_PB_INT_IF (*((PUINT16V)0x4000109E)) // RW1, GPIO PB interrupt flag + +/* GPIO PA register */ +#define R32_PA_DIR (*((PUINT32V)0x400010A0)) // RW, GPIO PA I/O direction: 0=in, 1=out +#define R8_PA_DIR_0 (*((PUINT8V)0x400010A0)) // RW, GPIO PA I/O direction byte 0 +#define R8_PA_DIR_1 (*((PUINT8V)0x400010A1)) // RW, GPIO PA I/O direction byte 1 +#define R32_PA_PIN (*((PUINT32V)0x400010A4)) // RO, GPIO PA input +#define R8_PA_PIN_0 (*((PUINT8V)0x400010A4)) // RO, GPIO PA input byte 0 +#define R8_PA_PIN_1 (*((PUINT8V)0x400010A5)) // RO, GPIO PA input byte 1 +#define R32_PA_OUT (*((PUINT32V)0x400010A8)) // RW, GPIO PA output +#define R8_PA_OUT_0 (*((PUINT8V)0x400010A8)) // RW, GPIO PA output byte 0 +#define R8_PA_OUT_1 (*((PUINT8V)0x400010A9)) // RW, GPIO PA output byte 1 +#define R32_PA_CLR (*((PUINT32V)0x400010AC)) // WZ, GPIO PA clear output: 0=keep, 1=clear +#define R8_PA_CLR_0 (*((PUINT8V)0x400010AC)) // WZ, GPIO PA clear output byte 0 +#define R8_PA_CLR_1 (*((PUINT8V)0x400010AD)) // WZ, GPIO PA clear output byte 1 +#define R32_PA_PU (*((PUINT32V)0x400010B0)) // RW, GPIO PA pullup resistance enable +#define R8_PA_PU_0 (*((PUINT8V)0x400010B0)) // RW, GPIO PA pullup resistance enable byte 0 +#define R8_PA_PU_1 (*((PUINT8V)0x400010B1)) // RW, GPIO PA pullup resistance enable byte 1 +#define R32_PA_PD_DRV (*((PUINT32V)0x400010B4)) // RW, PA pulldown for input or PA driving capability for output +#define R8_PA_PD_DRV_0 (*((PUINT8V)0x400010B4)) // RW, PA pulldown for input or PA driving capability for output byte 0 +#define R8_PA_PD_DRV_1 (*((PUINT8V)0x400010B5)) // RW, PA pulldown for input or PA driving capability for output byte 1 + +/* GPIO PB register */ +#define R32_PB_DIR (*((PUINT32V)0x400010C0)) // RW, GPIO PB I/O direction: 0=in, 1=out +#define R8_PB_DIR_0 (*((PUINT8V)0x400010C0)) // RW, GPIO PB I/O direction byte 0 +#define R8_PB_DIR_1 (*((PUINT8V)0x400010C1)) // RW, GPIO PB I/O direction byte 1 +#define R8_PB_DIR_2 (*((PUINT8V)0x400010C2)) // RW, GPIO PB I/O direction byte 2 +#define R32_PB_PIN (*((PUINT32V)0x400010C4)) // RO, GPIO PB input +#define R8_PB_PIN_0 (*((PUINT8V)0x400010C4)) // RO, GPIO PB input byte 0 +#define R8_PB_PIN_1 (*((PUINT8V)0x400010C5)) // RO, GPIO PB input byte 1 +#define R8_PB_PIN_2 (*((PUINT8V)0x400010C6)) // RO, GPIO PB input byte 2 +#define R32_PB_OUT (*((PUINT32V)0x400010C8)) // RW, GPIO PB output +#define R8_PB_OUT_0 (*((PUINT8V)0x400010C8)) // RW, GPIO PB output byte 0 +#define R8_PB_OUT_1 (*((PUINT8V)0x400010C9)) // RW, GPIO PB output byte 1 +#define R8_PB_OUT_2 (*((PUINT8V)0x400010CA)) // RW, GPIO PB output byte 2 +#define R32_PB_CLR (*((PUINT32V)0x400010CC)) // WZ, GPIO PB clear output: 0=keep, 1=clear +#define R8_PB_CLR_0 (*((PUINT8V)0x400010CC)) // WZ, GPIO PB clear output byte 0 +#define R8_PB_CLR_1 (*((PUINT8V)0x400010CD)) // WZ, GPIO PB clear output byte 1 +#define R8_PB_CLR_2 (*((PUINT8V)0x400010CE)) // WZ, GPIO PB clear output byte 2 +#define R32_PB_PU (*((PUINT32V)0x400010D0)) // RW, GPIO PB pullup resistance enable +#define R8_PB_PU_0 (*((PUINT8V)0x400010D0)) // RW, GPIO PB pullup resistance enable byte 0 +#define R8_PB_PU_1 (*((PUINT8V)0x400010D1)) // RW, GPIO PB pullup resistance enable byte 1 +#define R8_PB_PU_2 (*((PUINT8V)0x400010D2)) // RW, GPIO PB pullup resistance enable byte 2 +#define R32_PB_PD_DRV (*((PUINT32V)0x400010D4)) // RW, PB pulldown for input or PB driving capability for output +#define R8_PB_PD_DRV_0 (*((PUINT8V)0x400010D4)) // RW, PB pulldown for input or PB driving capability for output byte 0 +#define R8_PB_PD_DRV_1 (*((PUINT8V)0x400010D5)) // RW, PB pulldown for input or PB driving capability for output byte 1 +#define R8_PB_PD_DRV_2 (*((PUINT8V)0x400010D6)) // RW, PB pulldown for input or PB driving capability for output byte 2 + +/* GPIO register address offset and bit define */ +#define BA_PA ((PUINT8V)0x400010A0) // point GPIO PA base address +#define BA_PB ((PUINT8V)0x400010C0) // point GPIO PB base address +#define GPIO_DIR 0x00 +#define GPIO_DIR_0 0x00 +#define GPIO_DIR_1 0x01 +#define GPIO_DIR_2 0x02 +#define GPIO_PIN 0x04 +#define GPIO_PIN_0 0x04 +#define GPIO_PIN_1 0x05 +#define GPIO_PIN_2 0x06 +#define GPIO_OUT 0x08 +#define GPIO_OUT_0 0x08 +#define GPIO_OUT_1 0x09 +#define GPIO_OUT_2 0x0A +#define GPIO_CLR 0x0C +#define GPIO_CLR_0 0x0C +#define GPIO_CLR_1 0x0D +#define GPIO_CLR_2 0x0E +#define GPIO_PU 0x10 +#define GPIO_PU_0 0x10 +#define GPIO_PU_1 0x11 +#define GPIO_PU_2 0x12 +#define GPIO_PD_DRV 0x14 +#define GPIO_PD_DRV_0 0x14 +#define GPIO_PD_DRV_1 0x15 +#define GPIO_PD_DRV_2 0x16 + +/* GPIO alias name */ +#define bAIN9 (1<<0) // PA0 +#define bSCK1 (1<<0) // PA0 +#define bAIN8 (1<<1) // PA1 +#define bSDO (1<<1) // PA1 +#define bMOSI1 bSDO +#define bAIN7 (1<<2) // PA2 +#define bTMR3_ (1<<2) // PA2 +#define bCAP3_ bTMR3_ +#define bPWM3_ bTMR3_ +#define bSDI (1<<2) // PA2 +#define bMISO1 bSDI +#define bAIN6 (1<<3) // PA3 +#define bAIN0 (1<<4) // PA4 +#define bRXD3 (1<<4) // PA4 +#define bAIN1 (1<<5) // PA5 +#define bTXD3 (1<<5) // PA5 +#define bAIN10 (1<<6) // PA6 +#define bRXD2 (1<<6) // PA6 +#define bPWM4_ (1<<6) // PA6 +#define bAIN11 (1<<7) // PA7 +#define bTXD2 (1<<7) // PA7 +#define bPWM5_ (1<<7) // PA7 +#define bAIN12 (1<<8) // PA8 +#define bRXD1 (1<<8) // PA8 +#define bAIN13 (1<<9) // PA9 +#define bTMR0 (1<<9) // PA9 +#define bCAP0 bTMR0 +#define bPWM0 bTMR0 +#define bTXD1 (1<<9) // PA9 +#define bX32KI (1<<10) // PA10 +#define bTMR1 (1<<10) // PA10 +#define bCAP1 bTMR1 +#define bPWM1 bTMR1 +#define bX32KO (1<<11) // PA11 +#define bTMR2 (1<<11) // PA11 +#define bCAP2 bTMR2 +#define bPWM2 bTMR2 +#define bAIN2 (1<<12) // PA12 +#define bPWM4 (1<<12) // PA12 +#define bSCS (1<<12) // PA12 +#define bAIN3 (1<<13) // PA13 +#define bSCK0 (1<<13) // PA13 +#define bPWM5 (1<<13) // PA13 +#define bAIN4 (1<<14) // PA14 +#define bMOSI (1<<14) // PA14 +#define bTXD0_ (1<<14) // PA14 +#define bAIN5 (1<<15) // PA15 +#define bMISO (1<<15) // PA15 +#define bRXD0_ (1<<15) // PA15 +#define bPWM6 (1<<0) // PB0 +#define bCTS (1<<0) // PB0 +#define bDSR (1<<1) // PB1 +#define bPWM7_ (1<<1) // PB1 +#define bRI (1<<2) // PB2 +#define bPWM8_ (1<<2) // PB2 +#define bDCD (1<<3) // PB3 +#define bPWM9_ (1<<3) // PB3 +#define bPWM7 (1<<4) // PB4 +#define bRXD0 (1<<4) // PB4 +#define bDTR (1<<5) // PB5 +#define bRTS (1<<6) // PB6 +#define bPWM8 (1<<6) // PB6 +#define bTXD0 (1<<7) // PB7 +#define bPWM9 (1<<7) // PB7 +#define bUDM (1<<10) // PB10 +#define bTMR1_ (1<<10) // PB10 +#define bCAP1_ bTMR1_ +#define bPWM1_ bTMR1_ +#define bUDP (1<<11) // PB11 +#define bTMR2_ (1<<11) // PB11 +#define bCAP2_ bTMR2_ +#define bPWM2_ bTMR2_ +#define bU2DM (1<<12) // PB12 +#define bSCS_ (1<<12) // PB12 +#define bSDA (1<<12) // PB12 +#define bRXD1_ (1<<12) // PB12 +#define bU2DP (1<<13) // PB13 +#define bSCK0_ (1<<13) // PB13 +#define bSCL (1<<13) // PB13 +#define bTXD1_ (1<<13) // PB13 +#define bTIO (1<<14) // PB14 +#define bDSR_ (1<<14) // PB14 +#define bMOSI_ (1<<14) // PB14 +#define bPWM10 (1<<14) // PB14 +#define bTCK (1<<15) // PB15 +#define bMISO_ (1<<15) // PB15 +#define bDTR_ (1<<15) // PB15 +#define bSDA_ (1<<20) // PB20 +#define bRXD3_ (1<<20) // PB20 +#define bSCL_ (1<<21) // PB21 +#define bTXD3_ (1<<21) // PB21 +#define bRXD2_ (1<<22) // PB22 +#define bTMR3 (1<<22) // PB22 +#define bCAP3 bTMR3 +#define bPWM3 bTMR3 +#define bRST (1<<23) // PB23 +#define bTMR0_ (1<<23) // PB23 +#define bCAP0_ bTMR0_ +#define bPWM0_ bTMR0_ +#define bTXD2_ (1<<23) // PB23 +#define bPWM11 (1<<23) // PB23 + +/* Timer0 register */ +#define R32_TMR0_CONTROL (*((PUINT32V)0x40002000)) // RW, TMR0 control +#define R8_TMR0_CTRL_MOD (*((PUINT8V)0x40002000)) // RW, TMR0 mode control +#define R8_TMR0_INTER_EN (*((PUINT8V)0x40002002)) // RW, TMR0 interrupt enable +#define R32_TMR0_STATUS (*((PUINT32V)0x40002004)) // RW, TMR0 status +#define R8_TMR0_INT_FLAG (*((PUINT8V)0x40002006)) // RW1, TMR0 interrupt flag +#define R8_TMR0_FIFO_COUNT (*((PUINT8V)0x40002007)) // RO, TMR0 FIFO count status +#define R32_TMR0_COUNT (*((PUINT32V)0x40002008)) // RO, TMR0 current count +#define R16_TMR0_COUNT (*((PUINT16V)0x40002008)) // RO, TMR0 current count +#define R8_TMR0_COUNT (*((PUINT8V)0x40002008)) // RO, TMR0 current count +#define R32_TMR0_CNT_END (*((PUINT32V)0x4000200C)) // RW, TMR0 end count value, only low 26 bit +#define R32_TMR0_FIFO (*((PUINT32V)0x40002010)) // RO/WO, TMR0 FIFO register, only low 26 bit +#define R16_TMR0_FIFO (*((PUINT16V)0x40002010)) // RO/WO, TMR0 FIFO register +#define R8_TMR0_FIFO (*((PUINT8V)0x40002010)) // RO/WO, TMR0 FIFO register + +/* Timer1 register */ +#define R32_TMR1_CONTROL (*((PUINT32V)0x40002400)) // RW, TMR1 control +#define R8_TMR1_CTRL_MOD (*((PUINT8V)0x40002400)) // RW, TMR1 mode control +#define R8_TMR1_CTRL_DMA (*((PUINT8V)0x40002401)) // RW, TMR1 DMA control +#define R8_TMR1_INTER_EN (*((PUINT8V)0x40002402)) // RW, TMR1 interrupt enable +#define R32_TMR1_STATUS (*((PUINT32V)0x40002404)) // RW, TMR1 status +#define R8_TMR1_INT_FLAG (*((PUINT8V)0x40002406)) // RW1, TMR1 interrupt flag +#define R8_TMR1_FIFO_COUNT (*((PUINT8V)0x40002407)) // RO, TMR1 FIFO count status +#define R32_TMR1_COUNT (*((PUINT32V)0x40002408)) // RO, TMR1 current count +#define R16_TMR1_COUNT (*((PUINT16V)0x40002408)) // RO, TMR1 current count +#define R8_TMR1_COUNT (*((PUINT8V)0x40002408)) // RO, TMR1 current count +#define R32_TMR1_CNT_END (*((PUINT32V)0x4000240C)) // RW, TMR1 end count value, only low 26 bit +#define R32_TMR1_FIFO (*((PUINT32V)0x40002410)) // RO/WO, TMR1 FIFO register, only low 26 bit +#define R16_TMR1_FIFO (*((PUINT16V)0x40002410)) // RO/WO, TMR1 FIFO register +#define R8_TMR1_FIFO (*((PUINT8V)0x40002410)) // RO/WO, TMR1 FIFO register +#define R32_TMR1_DMA_NOW (*((PUINT32V)0x40002414)) // RW, TMR1 DMA current address +#define R16_TMR1_DMA_NOW (*((PUINT16V)0x40002414)) // RW, TMR1 DMA current address +#define R32_TMR1_DMA_BEG (*((PUINT32V)0x40002418)) // RW, TMR1 DMA begin address +#define R16_TMR1_DMA_BEG (*((PUINT16V)0x40002418)) // RW, TMR1 DMA begin address +#define R32_TMR1_DMA_END (*((PUINT32V)0x4000241C)) // RW, TMR1 DMA end address +#define R16_TMR1_DMA_END (*((PUINT16V)0x4000241C)) // RW, TMR1 DMA end address + +/* Timer2 register */ +#define R32_TMR2_CONTROL (*((PUINT32V)0x40002800)) // RW, TMR2 control +#define R8_TMR2_CTRL_MOD (*((PUINT8V)0x40002800)) // RW, TMR2 mode control +#define R8_TMR2_CTRL_DMA (*((PUINT8V)0x40002801)) // RW, TMR2 DMA control +#define R8_TMR2_INTER_EN (*((PUINT8V)0x40002802)) // RW, TMR2 interrupt enable +#define R32_TMR2_STATUS (*((PUINT32V)0x40002804)) // RW, TMR2 status +#define R8_TMR2_INT_FLAG (*((PUINT8V)0x40002806)) // RW1, TMR2 interrupt flag +#define R8_TMR2_FIFO_COUNT (*((PUINT8V)0x40002807)) // RO, TMR2 FIFO count status +#define R32_TMR2_COUNT (*((PUINT32V)0x40002808)) // RO, TMR2 current count +#define R16_TMR2_COUNT (*((PUINT16V)0x40002808)) // RO, TMR2 current count +#define R8_TMR2_COUNT (*((PUINT8V)0x40002808)) // RO, TMR2 current count +#define R32_TMR2_CNT_END (*((PUINT32V)0x4000280C)) // RW, TMR2 end count value, only low 26 bit +#define R32_TMR2_FIFO (*((PUINT32V)0x40002810)) // RO/WO, TMR2 FIFO register, only low 26 bit +#define R16_TMR2_FIFO (*((PUINT16V)0x40002810)) // RO/WO, TMR2 FIFO register +#define R8_TMR2_FIFO (*((PUINT8V)0x40002810)) // RO/WO, TMR2 FIFO register +#define R32_TMR2_DMA_NOW (*((PUINT32V)0x40002814)) // RW, TMR2 DMA current address +#define R16_TMR2_DMA_NOW (*((PUINT16V)0x40002814)) // RW, TMR2 DMA current address +#define R32_TMR2_DMA_BEG (*((PUINT32V)0x40002818)) // RW, TMR2 DMA begin address +#define R16_TMR2_DMA_BEG (*((PUINT16V)0x40002818)) // RW, TMR2 DMA begin address +#define R32_TMR2_DMA_END (*((PUINT32V)0x4000281C)) // RW, TMR2 DMA end address +#define R16_TMR2_DMA_END (*((PUINT16V)0x4000281C)) // RW, TMR2 DMA end address + +/* Timer3 register */ +#define R32_TMR3_CONTROL (*((PUINT32V)0x40002C00)) // RW, TMR3 control +#define R8_TMR3_CTRL_MOD (*((PUINT8V)0x40002C00)) // RW, TMR3 mode control +#define R8_TMR3_INTER_EN (*((PUINT8V)0x40002C02)) // RW, TMR3 interrupt enable +#define R32_TMR3_STATUS (*((PUINT32V)0x40002C04)) // RW, TMR3 status +#define R8_TMR3_INT_FLAG (*((PUINT8V)0x40002C06)) // RW1, TMR3 interrupt flag +#define R8_TMR3_FIFO_COUNT (*((PUINT8V)0x40002C07)) // RO, TMR3 FIFO count status +#define R32_TMR3_COUNT (*((PUINT32V)0x40002C08)) // RO, TMR3 current count +#define R16_TMR3_COUNT (*((PUINT16V)0x40002C08)) // RO, TMR3 current count +#define R8_TMR3_COUNT (*((PUINT8V)0x40002C08)) // RO, TMR3 current count +#define R32_TMR3_CNT_END (*((PUINT32V)0x40002C0C)) // RW, TMR3 end count value, only low 26 bit +#define R32_TMR3_FIFO (*((PUINT32V)0x40002C10)) // RO/WO, TMR3 FIFO register, only low 26 bit +#define R16_TMR3_FIFO (*((PUINT16V)0x40002C10)) // RO/WO, TMR3 FIFO register +#define R8_TMR3_FIFO (*((PUINT8V)0x40002C10)) // RO/WO, TMR3 FIFO register + +/* Timer register address offset and bit define */ +#define TMR_FIFO_SIZE 8 // timer FIFO size (depth) +#define BA_TMR0 ((PUINT8V)0x40002000) // point TMR0 base address +#define BA_TMR1 ((PUINT8V)0x40002400) // point TMR1 base address +#define BA_TMR2 ((PUINT8V)0x40002800) // point TMR2 base address +#define BA_TMR3 ((PUINT8V)0x40002C00) // point TMR3 base address +#define TMR_CTRL_MOD 0 +#define RB_TMR_MODE_IN 0x01 // RW, timer in mode: 0=timer/PWM, 1=capture/count +#define RB_TMR_ALL_CLEAR 0x02 // RW, force clear timer FIFO and count +#define RB_TMR_COUNT_EN 0x04 // RW, timer count enable +#define RB_TMR_OUT_EN 0x08 // RW, timer output enable +#define RB_TMR_OUT_POLAR 0x10 // RW, timer PWM output polarity: 0=default low and high action, 1=default high and low action +#define RB_TMR_CAP_COUNT 0x10 // RW, count sub-mode if RB_TMR_MODE_IN=1: 0=capture, 1=count +#define RB_TMR_PWM_REPEAT 0xC0 // RW, timer PWM repeat mode: 00=1, 01=4, 10=8, 11-16 +#define RB_TMR_CAP_EDGE 0xC0 // RW, timer capture edge mode: 00=disable, 01=edge change, 10=fall to fall, 11-rise to rise +#define TMR_CTRL_DMA 1 +#define RB_TMR_DMA_ENABLE 0x01 // RW, timer1/2 DMA enable +#define RB_TMR_DMA_LOOP 0x04 // RW, timer1/2 DMA address loop enable +#define TMR_INTER_EN 2 +#define RB_TMR_IE_CYC_END 0x01 // RW, enable interrupt for timer capture count timeout or PWM cycle end +#define RB_TMR_IE_DATA_ACT 0x02 // RW, enable interrupt for timer capture input action or PWM trigger +#define RB_TMR_IE_FIFO_HF 0x04 // RW, enable interrupt for timer FIFO half (capture fifo >=4 or PWM fifo <=3) +#define RB_TMR_IE_DMA_END 0x08 // RW, enable interrupt for timer1/2 DMA completion +#define RB_TMR_IE_FIFO_OV 0x10 // RW, enable interrupt for timer FIFO overflow +#define TMR_INT_FLAG 6 +#define RB_TMR_IF_CYC_END 0x01 // RW1, interrupt flag for timer capture count timeout or PWM cycle end +#define RB_TMR_IF_DATA_ACT 0x02 // RW1, interrupt flag for timer capture input action or PWM trigger +#define RB_TMR_IF_FIFO_HF 0x04 // RW1, interrupt flag for timer FIFO half (capture fifo >=4 or PWM fifo <=3) +#define RB_TMR_IF_DMA_END 0x08 // RW1, interrupt flag for timer1/2 DMA completion +#define RB_TMR_IF_FIFO_OV 0x10 // RW1, interrupt flag for timer FIFO overflow +#define TMR_FIFO_COUNT 7 +#define TMR_COUNT 0x08 +#define TMR_CNT_END 0x0C +#define TMR_FIFO 0x10 +#define TMR_DMA_NOW 0x14 +#define TMR_DMA_BEG 0x18 +#define TMR_DMA_END 0x1C + +/* UART0 register */ +#define R32_UART0_CTRL (*((PUINT32V)0x40003000)) // RW, UART0 control +#define R8_UART0_MCR (*((PUINT8V)0x40003000)) // RW, UART0 modem control +#define R8_UART0_IER (*((PUINT8V)0x40003001)) // RW, UART0 interrupt enable +#define R8_UART0_FCR (*((PUINT8V)0x40003002)) // RW, UART0 FIFO control +#define R8_UART0_LCR (*((PUINT8V)0x40003003)) // RW, UART0 line control +#define R32_UART0_STAT (*((PUINT32V)0x40003004)) // RO, UART0 status +#define R8_UART0_IIR (*((PUINT8V)0x40003004)) // RO, UART0 interrupt identification +#define R8_UART0_LSR (*((PUINT8V)0x40003005)) // RO, UART0 line status +#define R8_UART0_MSR (*((PUINT8V)0x40003006)) // RO, UART0 modem status +#define R32_UART0_FIFO (*((PUINT32V)0x40003008)) // RW, UART0 data or FIFO port +#define R8_UART0_RBR (*((PUINT8V)0x40003008)) // RO, UART0 receiver buffer, receiving byte +#define R8_UART0_THR (*((PUINT8V)0x40003008)) // WO, UART0 transmitter holding, transmittal byte +#define R8_UART0_RFC (*((PUINT8V)0x4000300A)) // RO, UART0 receiver FIFO count +#define R8_UART0_TFC (*((PUINT8V)0x4000300B)) // RO, UART0 transmitter FIFO count +#define R32_UART0_SETUP (*((PUINT32V)0x4000300C)) // RW, UART0 setup +#define R16_UART0_DL (*((PUINT16V)0x4000300C)) // RW, UART0 divisor latch +#define R8_UART0_DLL (*((PUINT8V)0x4000300C)) // RW, UART0 divisor latch LSB byte +#define R8_UART0_DLM (*((PUINT8V)0x4000300D)) // RW, UART0 divisor latch MSB byte +#define R8_UART0_DIV (*((PUINT8V)0x4000300E)) // RW, UART0 pre-divisor latch byte, only low 7 bit, from 1 to 0/128 +#define R8_UART0_ADR (*((PUINT8V)0x4000300F)) // RW, UART0 slave address: 0xFF=disable, other=enable + +/* UART1 register */ +#define R32_UART1_CTRL (*((PUINT32V)0x40003400)) // RW, UART1 control +#define R8_UART1_MCR (*((PUINT8V)0x40003400)) // RW, UART1 modem control +#define R8_UART1_IER (*((PUINT8V)0x40003401)) // RW, UART1 interrupt enable +#define R8_UART1_FCR (*((PUINT8V)0x40003402)) // RW, UART1 FIFO control +#define R8_UART1_LCR (*((PUINT8V)0x40003403)) // RW, UART1 line control +#define R32_UART1_STAT (*((PUINT32V)0x40003404)) // RO, UART1 status +#define R8_UART1_IIR (*((PUINT8V)0x40003404)) // RO, UART1 interrupt identification +#define R8_UART1_LSR (*((PUINT8V)0x40003405)) // RO, UART1 line status +#define R32_UART1_FIFO (*((PUINT32V)0x40003408)) // RW, UART1 data or FIFO port +#define R8_UART1_RBR (*((PUINT8V)0x40003408)) // RO, UART1 receiver buffer, receiving byte +#define R8_UART1_THR (*((PUINT8V)0x40003408)) // WO, UART1 transmitter holding, transmittal byte +#define R8_UART1_RFC (*((PUINT8V)0x4000340A)) // RO, UART1 receiver FIFO count +#define R8_UART1_TFC (*((PUINT8V)0x4000340B)) // RO, UART1 transmitter FIFO count +#define R32_UART1_SETUP (*((PUINT32V)0x4000340C)) // RW, UART1 setup +#define R16_UART1_DL (*((PUINT16V)0x4000340C)) // RW, UART1 divisor latch +#define R8_UART1_DLL (*((PUINT8V)0x4000340C)) // RW, UART1 divisor latch LSB byte +#define R8_UART1_DLM (*((PUINT8V)0x4000340D)) // RW, UART1 divisor latch MSB byte +#define R8_UART1_DIV (*((PUINT8V)0x4000340E)) // RW, UART1 pre-divisor latch byte, only low 7 bit, from 1 to 0/128 + +/* UART2 register */ +#define R32_UART2_CTRL (*((PUINT32V)0x40003800)) // RW, UART2 control +#define R8_UART2_MCR (*((PUINT8V)0x40003800)) // RW, UART2 modem control +#define R8_UART2_IER (*((PUINT8V)0x40003801)) // RW, UART2 interrupt enable +#define R8_UART2_FCR (*((PUINT8V)0x40003802)) // RW, UART2 FIFO control +#define R8_UART2_LCR (*((PUINT8V)0x40003803)) // RW, UART2 line control +#define R32_UART2_STAT (*((PUINT32V)0x40003804)) // RO, UART2 status +#define R8_UART2_IIR (*((PUINT8V)0x40003804)) // RO, UART2 interrupt identification +#define R8_UART2_LSR (*((PUINT8V)0x40003805)) // RO, UART2 line status +#define R32_UART2_FIFO (*((PUINT32V)0x40003808)) // RW, UART2 data or FIFO port +#define R8_UART2_RBR (*((PUINT8V)0x40003808)) // RO, UART2 receiver buffer, receiving byte +#define R8_UART2_THR (*((PUINT8V)0x40003808)) // WO, UART2 transmitter holding, transmittal byte +#define R8_UART2_RFC (*((PUINT8V)0x4000380A)) // RO, UART2 receiver FIFO count +#define R8_UART2_TFC (*((PUINT8V)0x4000380B)) // RO, UART2 transmitter FIFO count +#define R32_UART2_SETUP (*((PUINT32V)0x4000380C)) // RW, UART2 setup +#define R16_UART2_DL (*((PUINT16V)0x4000380C)) // RW, UART2 divisor latch +#define R8_UART2_DLL (*((PUINT8V)0x4000380C)) // RW, UART2 divisor latch LSB byte +#define R8_UART2_DLM (*((PUINT8V)0x4000380D)) // RW, UART2 divisor latch MSB byte +#define R8_UART2_DIV (*((PUINT8V)0x4000380E)) // RW, UART2 pre-divisor latch byte, only low 7 bit, from 1 to 0/128 + +/* UART3 register */ +#define R32_UART3_CTRL (*((PUINT32V)0x40003C00)) // RW, UART3 control +#define R8_UART3_MCR (*((PUINT8V)0x40003C00)) // RW, UART3 modem control +#define R8_UART3_IER (*((PUINT8V)0x40003C01)) // RW, UART3 interrupt enable +#define R8_UART3_FCR (*((PUINT8V)0x40003C02)) // RW, UART3 FIFO control +#define R8_UART3_LCR (*((PUINT8V)0x40003C03)) // RW, UART3 line control +#define R32_UART3_STAT (*((PUINT32V)0x40003C04)) // RO, UART3 status +#define R8_UART3_IIR (*((PUINT8V)0x40003C04)) // RO, UART3 interrupt identification +#define R8_UART3_LSR (*((PUINT8V)0x40003C05)) // RO, UART3 line status +#define R32_UART3_FIFO (*((PUINT32V)0x40003C08)) // RW, UART3 data or FIFO port +#define R8_UART3_RBR (*((PUINT8V)0x40003C08)) // RO, UART3 receiver buffer, receiving byte +#define R8_UART3_THR (*((PUINT8V)0x40003C08)) // WO, UART3 transmitter holding, transmittal byte +#define R8_UART3_RFC (*((PUINT8V)0x40003C0A)) // RO, UART3 receiver FIFO count +#define R8_UART3_TFC (*((PUINT8V)0x40003C0B)) // RO, UART3 transmitter FIFO count +#define R32_UART3_SETUP (*((PUINT32V)0x40003C0C)) // RW, UART3 setup +#define R16_UART3_DL (*((PUINT16V)0x40003C0C)) // RW, UART3 divisor latch +#define R8_UART3_DLL (*((PUINT8V)0x40003C0C)) // RW, UART3 divisor latch LSB byte +#define R8_UART3_DLM (*((PUINT8V)0x40003C0D)) // RW, UART3 divisor latch MSB byte +#define R8_UART3_DIV (*((PUINT8V)0x40003C0E)) // RW, UART3 pre-divisor latch byte, only low 7 bit, from 1 to 0/128 + +/* UART register address offset and bit define */ +#define UART_FIFO_SIZE 8 // UART FIFO size (depth) +#define UART_RECV_RDY_SZ 7 // the max FIFO trigger level for UART receiver data available +#define BA_UART0 ((PUINT8V)0x40003000) // point UART0 base address +#define BA_UART1 ((PUINT8V)0x40003400) // point UART1 base address +#define BA_UART2 ((PUINT8V)0x40003800) // point UART2 base address +#define BA_UART3 ((PUINT8V)0x40003C00) // point UART3 base address +#define UART_MCR 0 +#define RB_MCR_DTR 0x01 // RW, UART0 control DTR +#define RB_MCR_RTS 0x02 // RW, UART0 control RTS +#define RB_MCR_OUT1 0x04 // RW, UART0 control OUT1 +#define RB_MCR_OUT2 0x08 // RW, UART control OUT2 +#define RB_MCR_INT_OE 0x08 // RW, UART interrupt output enable +#define RB_MCR_LOOP 0x10 // RW, UART0 enable local loop back +#define RB_MCR_AU_FLOW_EN 0x20 // RW, UART0 enable autoflow control +#define RB_MCR_TNOW 0x40 // RW, UART0 enable TNOW output on DTR pin +#define RB_MCR_HALF 0x80 // RW, UART0 enable half-duplex +#define UART_IER 1 +#define RB_IER_RECV_RDY 0x01 // RW, UART interrupt enable for receiver data ready +#define RB_IER_THR_EMPTY 0x02 // RW, UART interrupt enable for THR empty +#define RB_IER_LINE_STAT 0x04 // RW, UART interrupt enable for receiver line status +#define RB_IER_MODEM_CHG 0x08 // RW, UART0 interrupt enable for modem status change +#define RB_IER_DTR_EN 0x10 // RW, UART0 DTR/TNOW output pin enable +#define RB_IER_RTS_EN 0x20 // RW, UART0 RTS output pin enable +#define RB_IER_TXD_EN 0x40 // RW, UART TXD pin enable +#define RB_IER_RESET 0x80 // WZ, UART software reset control, high action, auto clear +#define UART_FCR 2 +#define RB_FCR_FIFO_EN 0x01 // RW, UART FIFO enable +#define RB_FCR_RX_FIFO_CLR 0x02 // WZ, clear UART receiver FIFO, high action, auto clear +#define RB_FCR_TX_FIFO_CLR 0x04 // WZ, clear UART transmitter FIFO, high action, auto clear +#define RB_FCR_FIFO_TRIG 0xC0 // RW, UART receiver FIFO trigger level: 00-1byte, 01-2bytes, 10-4bytes, 11-7bytes +#define UART_LCR 3 +#define RB_LCR_WORD_SZ 0x03 // RW, UART word bit length: 00-5bit, 01-6bit, 10-7bit, 11-8bit +#define RB_LCR_STOP_BIT 0x04 // RW, UART stop bit length: 0-1bit, 1-2bit +#define RB_LCR_PAR_EN 0x08 // RW, UART parity enable +#define RB_LCR_PAR_MOD 0x30 // RW, UART parity mode: 00-odd, 01-even, 10-mark, 11-space +#define RB_LCR_BREAK_EN 0x40 // RW, UART break control enable +#define RB_LCR_DLAB 0x80 // RW, UART reserved bit +#define RB_LCR_GP_BIT 0x80 // RW, UART general purpose bit +#define UART_IIR 4 +#define RB_IIR_NO_INT 0x01 // RO, UART no interrupt flag: 0=interrupt action, 1=no interrupt +#define RB_IIR_INT_MASK 0x0F // RO, UART interrupt flag bit mask +#define RB_IIR_FIFO_ID 0xC0 // RO, UART FIFO enabled flag +#define UART_LSR 5 +#define RB_LSR_DATA_RDY 0x01 // RO, UART receiver fifo data ready status +#define RB_LSR_OVER_ERR 0x02 // RZ, UART receiver overrun error +#define RB_LSR_PAR_ERR 0x04 // RZ, UART receiver parity error +#define RB_LSR_FRAME_ERR 0x08 // RZ, UART receiver frame error +#define RB_LSR_BREAK_ERR 0x10 // RZ, UART receiver break error +#define RB_LSR_TX_FIFO_EMP 0x20 // RO, UART transmitter fifo empty status +#define RB_LSR_TX_ALL_EMP 0x40 // RO, UART transmitter all empty status +#define RB_LSR_ERR_RX_FIFO 0x80 // RO, indicate error in UART receiver fifo +#define UART_MSR 6 +#define RB_MSR_CTS_CHG 0x01 // RZ, UART0 CTS changed status, high action +#define RB_MSR_DSR_CHG 0x02 // RZ, UART0 DSR changed status, high action +//#define RB_MSR_RI_CHG 0x04 // RZ, UART0 RI changed status, high action +//#define RB_MSR_DCD_CHG 0x08 // RZ, UART0 DCD changed status, high action +#define RB_MSR_CTS 0x10 // RO, UART0 CTS action status +#define RB_MSR_DSR 0x20 // RO, UART0 DSR action status +//#define RB_MSR_RI 0x40 // RO, UART0 RI action status +//#define RB_MSR_DCD 0x80 // RO, UART0 DCD action status +#define UART_RBR 8 +#define UART_THR 8 +#define UART_RFC 0x0A +#define UART_TFC 0x0B +#define UART_DLL 0x0C +#define UART_DLM 0x0D +#define UART_DIV 0x0E +#define UART_ADR 0x0F + +/* UART interrupt identification values for IIR bits 3:0 */ +#define UART_II_SLV_ADDR 0x0E // RO, UART0 slave address match +#define UART_II_LINE_STAT 0x06 // RO, UART interrupt by receiver line status +#define UART_II_RECV_RDY 0x04 // RO, UART interrupt by receiver data available +#define UART_II_RECV_TOUT 0x0C // RO, UART interrupt by receiver fifo timeout +#define UART_II_THR_EMPTY 0x02 // RO, UART interrupt by THR empty +#define UART_II_MODEM_CHG 0x00 // RO, UART0 interrupt by modem status change +#define UART_II_NO_INTER 0x01 // RO, no UART interrupt is pending + +/* SPI0 register */ +#define R32_SPI0_CONTROL (*((PUINT32V)0x40004000)) // RW, SPI0 control +#define R8_SPI0_CTRL_MOD (*((PUINT8V)0x40004000)) // RW, SPI0 mode control +#define R8_SPI0_CTRL_CFG (*((PUINT8V)0x40004001)) // RW, SPI0 configuration control +#define R8_SPI0_INTER_EN (*((PUINT8V)0x40004002)) // RW, SPI0 interrupt enable +#define R8_SPI0_CLOCK_DIV (*((PUINT8V)0x40004003)) // RW, SPI0 master clock divisor +#define R8_SPI0_SLAVE_PRE (*((PUINT8V)0x40004003)) // RW, SPI0 slave preset value +#define R32_SPI0_STATUS (*((PUINT32V)0x40004004)) // RW, SPI0 status +#define R8_SPI0_BUFFER (*((PUINT8V)0x40004004)) // RO, SPI0 data buffer +#define R8_SPI0_RUN_FLAG (*((PUINT8V)0x40004005)) // RO, SPI0 work flag +#define R8_SPI0_INT_FLAG (*((PUINT8V)0x40004006)) // RW1, SPI0 interrupt flag +#define R8_SPI0_FIFO_COUNT (*((PUINT8V)0x40004007)) // RO, SPI0 FIFO count status +#define R32_SPI0_TOTAL_CNT (*((PUINT32V)0x4000400C)) // RW, SPI0 total byte count, only low 12 bit +#define R16_SPI0_TOTAL_CNT (*((PUINT16V)0x4000400C)) // RW, SPI0 total byte count, only low 12 bit +#define R32_SPI0_FIFO (*((PUINT32V)0x40004010)) // RW, SPI0 FIFO register +#define R8_SPI0_FIFO (*((PUINT8V)0x40004010)) // RO/WO, SPI0 FIFO register +#define R8_SPI0_FIFO_COUNT1 (*((PUINT8V)0x40004013)) // RO, SPI0 FIFO count status +#define R32_SPI0_DMA_NOW (*((PUINT32V)0x40004014)) // RW, SPI0 DMA current address +#define R16_SPI0_DMA_NOW (*((PUINT16V)0x40004014)) // RW, SPI0 DMA current address +#define R32_SPI0_DMA_BEG (*((PUINT32V)0x40004018)) // RW, SPI0 DMA begin address +#define R16_SPI0_DMA_BEG (*((PUINT16V)0x40004018)) // RW, SPI0 DMA begin address +#define R32_SPI0_DMA_END (*((PUINT32V)0x4000401C)) // RW, SPI0 DMA end address +#define R16_SPI0_DMA_END (*((PUINT16V)0x4000401C)) // RW, SPI0 DMA end address + +/* SPI1 register */ +#define R32_SPI1_CONTROL (*((PUINT32V)0x40004400)) // RW, SPI1 control +#define R8_SPI1_CTRL_MOD (*((PUINT8V)0x40004400)) // RW, SPI1 mode control +#define R8_SPI1_CTRL_CFG (*((PUINT8V)0x40004401)) // RW, SPI1 configuration control +#define R8_SPI1_INTER_EN (*((PUINT8V)0x40004402)) // RW, SPI1 interrupt enable +#define R8_SPI1_CLOCK_DIV (*((PUINT8V)0x40004403)) // RW, SPI1 master clock divisor +#define R32_SPI1_STATUS (*((PUINT32V)0x40004404)) // RW, SPI1 status +#define R8_SPI1_BUFFER (*((PUINT8V)0x40004404)) // RO, SPI1 data buffer +#define R8_SPI1_RUN_FLAG (*((PUINT8V)0x40004405)) // RO, SPI1 work flag +#define R8_SPI1_INT_FLAG (*((PUINT8V)0x40004406)) // RW1, SPI1 interrupt flag +#define R8_SPI1_FIFO_COUNT (*((PUINT8V)0x40004407)) // RO, SPI1 FIFO count status +#define R32_SPI1_TOTAL_CNT (*((PUINT32V)0x4000440C)) // RW, SPI1 total byte count, only low 12 bit +#define R16_SPI1_TOTAL_CNT (*((PUINT16V)0x4000440C)) // RW, SPI1 total byte count, only low 12 bit +#define R32_SPI1_FIFO (*((PUINT32V)0x40004410)) // RW, SPI1 FIFO register +#define R8_SPI1_FIFO (*((PUINT8V)0x40004410)) // RO/WO, SPI1 FIFO register +#define R8_SPI1_FIFO_COUNT1 (*((PUINT8V)0x40004413)) // RO, SPI1 FIFO count status + +/* SPI register address offset and bit define */ +#define SPI_FIFO_SIZE 8 // SPI FIFO size (depth) +#define BA_SPI0 ((PUINT8V)0x40004000) // point SPI0 base address +#define BA_SPI1 ((PUINT8V)0x40004400) // point SPI1 base address +#define SPI_CTRL_MOD 0 +#define RB_SPI_MODE_SLAVE 0x01 // RW, SPI0 slave mode: 0=master/host, 1=slave/device +#define RB_SPI_ALL_CLEAR 0x02 // RW, force clear SPI FIFO and count +#define RB_SPI_2WIRE_MOD 0x04 // RW, SPI0 enable 2 wire mode for slave: 0=3wire(SCK0,MOSI,MISO), 1=2wire(SCK0,MISO=MXSX) +#define RB_SPI_MST_SCK_MOD 0x08 // RW, SPI master clock mode: 0=mode 0, 1=mode 3 +#define RB_SPI_SLV_CMD_MOD 0x08 // RW, SPI0 slave command mode: 0=byte stream, 1=first byte command +#define RB_SPI_FIFO_DIR 0x10 // RW, SPI FIFO direction: 0=out(write @master mode), 1=in(read @master mode) +#define RB_SPI_SCK_OE 0x20 // RW, SPI SCK output enable +#define RB_SPI_MOSI_OE 0x40 // RW, SPI MOSI output enable +#define RB_SPI1_SDO_OE 0x40 // RW, SPI1 SDO output enable +#define RB_SPI_MISO_OE 0x80 // RW, SPI MISO output enable +#define RB_SPI1_SDI_OE 0x80 // RW, SPI1 SDI output enable, SPI1 enable 2 wire mode: 0=3wire(SCK1,SDO,SDI), 1=2wire(SCK1,SDI=SDX) +#define SPI_CTRL_CFG 1 +#define RB_SPI_DMA_ENABLE 0x01 // RW, SPI0 DMA enable +#define RB_SPI_DMA_LOOP 0x04 // RW, SPI0 DMA address loop enable +#define RB_SPI_AUTO_IF 0x10 // RW, enable buffer/FIFO accessing to auto clear RB_SPI_IF_BYTE_END interrupt flag +#define RB_SPI_BIT_ORDER 0x20 // RW, SPI bit data order: 0=MSB first, 1=LSB first +#define RB_SPI_MST_DLY_EN 0x40 // RW, SPI master input delay enable +#define SPI_INTER_EN 2 +#define RB_SPI_IE_CNT_END 0x01 // RW, enable interrupt for SPI total byte count end +#define RB_SPI_IE_BYTE_END 0x02 // RW, enable interrupt for SPI byte exchanged +#define RB_SPI_IE_FIFO_HF 0x04 // RW, enable interrupt for SPI FIFO half +#define RB_SPI_IE_DMA_END 0x08 // RW, enable interrupt for SPI0 DMA completion +#define RB_SPI_IE_FIFO_OV 0x10 // RW, enable interrupt for SPI0 FIFO overflow +#define RB_SPI_IE_FST_BYTE 0x80 // RW, enable interrupt for SPI0 slave mode first byte received +#define SPI_CLOCK_DIV 3 +#define SPI_SLAVE_PRESET 3 +#define SPI_BUFFER 4 +#define SPI_RUN_FLAG 5 +#define RB_SPI_SLV_CMD_ACT 0x10 // RO, SPI0 slave first byte / command flag +#define RB_SPI_FIFO_READY 0x20 // RO, SPI FIFO ready status +#define RB_SPI_SLV_CS_LOAD 0x40 // RO, SPI0 slave chip-select loading status +#define RB_SPI_SLV_SELECT 0x80 // RO, SPI0 slave selection status +#define SPI_INT_FLAG 6 +#define RB_SPI_IF_CNT_END 0x01 // RW1, interrupt flag for SPI total byte count end +#define RB_SPI_IF_BYTE_END 0x02 // RW1, interrupt flag for SPI byte exchanged +#define RB_SPI_IF_FIFO_HF 0x04 // RW1, interrupt flag for SPI FIFO half (RB_SPI_FIFO_DIR ? >=4bytes : <4bytes) +#define RB_SPI_IF_DMA_END 0x08 // RW1, interrupt flag for SPI0 DMA completion +#define RB_SPI_IF_FIFO_OV 0x10 // RW1, interrupt flag for SPI0 FIFO overflow +#define RB_SPI_FREE 0x40 // RO, current SPI free status +#define RB_SPI_IF_FST_BYTE 0x80 // RW1, interrupt flag for SPI0 slave mode first byte received +#define SPI_FIFO_COUNT 7 +#define SPI_TOTAL_CNT 0x0C +#define SPI_FIFO 0x10 +#define SPI_DMA_NOW 0x14 +#define SPI_DMA_BEG 0x18 +#define SPI_DMA_END 0x1C + +/* I2C register */ +#define R16_I2C_CTRL1 (*((PUINT16V)0x40004800)) // RW, I2C control 1 +#define R16_I2C_CTRL2 (*((PUINT16V)0x40004804)) // RW, I2C control 2 +#define R16_I2C_OADDR1 (*((PUINT16V)0x40004808)) // RW, I2C own address register 1 +#define R16_I2C_OADDR2 (*((PUINT16V)0x4000480C)) // RW, I2C own address register 2 +#define R16_I2C_DATAR (*((PUINT16V)0x40004810)) // RW, I2C data register +#define R16_I2C_STAR1 (*((PUINT16V)0x40004814)) // R0, I2C stauts register 1 +#define R16_I2C_STAR2 (*((PUINT16V)0x40004818)) // R0, I2C status register 2 +#define R8_I2C_PEC (*((PUINT8V) 0x40004819)) // R0, I2C Packet error checking register +#define R16_I2C_CKCFGR (*((PUINT16V)0x4000481C)) // RW, I2C clock control register +#define R16_I2C_RTR (*((PUINT16V)0x40004820)) // RW, I2C trise register + +/* I2C register address offset and bit define */ +#define BA_I2C ((PUINT8V)0x40004800) // point I2C base address +#define I2C_CTRL1 0 +#define RB_I2C_PE 0x0001 // RW, Peripheral enable +#define RB_I2C_SMBUS 0x0002 // RW, SMBUS mode: 0=I2C mode, 1=SMBUS mode +#define RB_I2C_SMBTYPE 0x0008 // RW, SMBus type: 0=Device, 1=Host +#define RB_I2C_EBARP 0x0010 // RW, ARP enable +#define RB_I2C_ENPEC 0x0020 // RW, PEC ebable +#define RB_I2C_ENGC 0x0040 // RW, General call enable +#define RB_I2C_NOSTRETCH 0x0080 // RW, Clock stretching disable (Slave mode) +#define RB_I2C_START 0x0100 // RW, Start generation: master mode: 0=no start, 1=repeated start; slave mode: 0=no start, 1=start at bus free +#define RB_I2C_STOP 0x0200 // RW, Stop generation: master mode: 0=no stop, 1=stop after the current byte transfer or after the current Start condition is sent; slave mode: 0=no stop, 1=Release the SCL and SDA lines after the current byte transfer +#define RB_I2C_ACK 0x0400 // RW, Acknowledge enable +#define RB_I2C_POS 0x0800 // RW, Acknowledge/PEC Position (for data reception) +#define RB_I2C_PEC 0x1000 // RW, Packet error checking: 0=No PEC transfer, 1=PEC transfer (in Tx or Rx mode) +#define RB_I2C_ALERT 0x2000 // RW, SMBus alert: 0=Releases SMBA pin high, 1=Drives SMBA pin low. +#define RB_I2C_SWRST 0x8000 // RW, Software reset +#define I2C_CTRL2 4 +#define RB_I2C_FREQ 0x003F // RW, Peripheral clock frequency, The minimum allowed frequency is 2 MHz,the maximum frequency is 36 MHz +#define RB_I2C_ITERREN 0x0100 // RW, Error interrupt enable +#define RB_I2C_ITEVTEN 0x0200 // RW, Event interrupt enable +#define RB_I2C_ITBUFEN 0x0400 // RW, Buffer interrupt enable +#define I2C_OADDR1 8 +#define RB_I2C_ADD0 0x0001 // RW, bit0 of address in 10-bit addressing mode +#define RB_I2C_ADD7_1 0x00FE // RW, bit[7:1] of address +#define RB_I2C_ADD9_8 0x0300 // RW, bit[9:8] of address in 10-bit addressing mode +#define RB_I2C_MUST1 0x4000 // RW, Should always be kept at 1 +#define RB_I2C_ADDMODE 0x8000 // RW, Addressing mode (slave mode): 0=7-bit slave address, 1=10-bit slave address +#define I2C_OADDR2 12 +#define RB_I2C_ENDUAL 0x0001 // RW, Dual addressing mode enable +#define RB_I2C_ADD2 0x00FE // RW, bit[7:1] of address2 +#define I2C_DATAR 16 +#define I2C_STAR1 20 +#define RB_I2C_SB 0x0001 // RW0, Start bit flag (Master mode) +#define RB_I2C_ADDR 0x0002 // RW0, Address sent (master mode)/matched (slave mode) flag +#define RB_I2C_BTF 0x0004 // RO, Byte transfer finished flag +#define RB_I2C_ADD10 0x0008 // RO, 10-bit header sent flag (Master mode) +#define RB_I2C_STOPF 0x0010 // RO, Stop detection flag (slave mode) +#define RB_I2C_RxNE 0x0040 // RO, Data register not empty flag (receivers) +#define RB_I2C_TxE 0x0080 // RO, Data register empty flag (transmitters) +#define RB_I2C_BERR 0x0100 // RW0, Bus error flag +#define RB_I2C_ARLO 0x0200 // RW0, Arbitration lost flag (master mode) +#define RB_I2C_AF 0x0400 // RW0, Acknowledge failure flag +#define RB_I2C_OVR 0x0800 // RW0, Overrun/Underrun flag +#define RB_I2C_PECERR 0x1000 // RW0, PEC Error flag in reception +#define RB_I2C_TIMEOUT 0x4000 // RW0, Timeout or Tlow error flag +#define RB_I2C_SMBALERT 0x8000 // RW0, SMBus alert flag +#define I2C_STAR2 24 +#define RB_I2C_MSL 0x0001 // RO, Mode statu: 0=Slave mode, 1=Master mode +#define RB_I2C_BUSY 0x0002 // RO, Bus busy flag +#define RB_I2C_TRA 0x0004 // RO, Trans flag: 0=data bytes received, 1=data bytes transmitted +#define RB_I2C_GENCALL 0x0010 // RO, General call address (Slave mode) received flag +#define RB_I2C_SMBDEFAULT 0x0020 // RO, SMBus device default address (Slave mode) received flag +#define RB_I2C_SMBHOST 0x0040 // RO, SMBus host header (Slave mode) received flag +#define RB_I2C_DUALF 0x0080 // RO, Dual flag (Slave mode): 0=Received address matched with OAR1, 1=Received address matched with OAR2 +#define RB_I2C_PECX 0xFF00 // RO, Packet error checking register +#define I2C_CKCFGR 28 +#define RB_I2C_CCR 0x0FFF // RW, Controls the SCL clock in Fm/Sm mode (Master mode) +#define RB_I2C_DUTY 0x4000 // RW, Fm mode duty cycle: 0=L/H=2, 1=L/H=16/9 +#define RB_I2C_F_S 0x8000 // RW, I2C master mode selection: 0=standard mode, 1=fast mode +#define I2C_RTR 32 +#define RB_I2C_TRISE 0x003F // RW, Maximum rise time in Fm/Sm mode (Master mode) + +/* PWM4/5/6/7/8/9/10/11 register */ +#define R32_PWM_CONTROL (*((PUINT32V)0x40005000)) // RW, PWM control +#define R8_PWM_OUT_EN (*((PUINT8V)0x40005000)) // RW, PWM output enable control +#define R8_PWM_POLAR (*((PUINT8V)0x40005001)) // RW, PWM output polarity control +#define R8_PWM_CONFIG (*((PUINT8V)0x40005002)) // RW, PWM configuration +#define R8_PWM_CLOCK_DIV (*((PUINT8V)0x40005003)) // RW, PWM clock divisor +#define R32_PWM4_7_DATA (*((PUINT32V)0x40005004)) // RW, PWM4-7 data holding +#define R8_PWM4_DATA (*((PUINT8V)0x40005004)) // RW, PWM4 data holding +#define R8_PWM5_DATA (*((PUINT8V)0x40005005)) // RW, PWM5 data holding +#define R8_PWM6_DATA (*((PUINT8V)0x40005006)) // RW, PWM6 data holding +#define R8_PWM7_DATA (*((PUINT8V)0x40005007)) // RW, PWM7 data holding +#define R32_PWM8_11_DATA (*((PUINT32V)0x40005008)) // RW, PWM8-11 data holding +#define R8_PWM8_DATA (*((PUINT8V)0x40005008)) // RW, PWM8 data holding +#define R8_PWM9_DATA (*((PUINT8V)0x40005009)) // RW, PWM9 data holding +#define R8_PWM10_DATA (*((PUINT8V)0x4000500A)) // RW, PWM10 data holding +#define R8_PWM11_DATA (*((PUINT8V)0x4000500B)) // RW, PWM11 data holding +#define R8_PWM_INT_CTRL (*((PUINT32V)0x4000500C)) // RW, PWM interrupt control +#define RB_PWM_IE_CYC 0x01 // RW, enable interrupt for PWM cycle end +#define RB_PWM_CYC_PRE 0x02 // RW, select PWM cycle interrupt point: 0=after count 0xFE (0x7E for 7 bits mode...), 1=after count 0xF0 (0x70 for 7 bits mode...) +#define RB_PWM_IF_CYC 0x80 // RW1, interrupt flag for PWM cycle end + +/* PWM4/5/6/7/8/9/10/11 register address offset and bit define */ +#define BA_PWMX ((PUINT8V)0x40005000) // point PWM4/5/6/7/8/9/10/11 base address +#define PWM_OUT_EN 0 +#define RB_PWM4_OUT_EN 0x01 // RW, PWM4 output enable +#define RB_PWM5_OUT_EN 0x02 // RW, PWM5 output enable +#define RB_PWM6_OUT_EN 0x04 // RW, PWM6 output enable +#define RB_PWM7_OUT_EN 0x08 // RW, PWM7 output enable +#define RB_PWM8_OUT_EN 0x10 // RW, PWM8 output enable +#define RB_PWM9_OUT_EN 0x20 // RW, PWM9 output enable +#define RB_PWM10_OUT_EN 0x40 // RW, PWM10 output enable +#define RB_PWM11_OUT_EN 0x80 // RW, PWM11 output enable +#define PWM_POLAR 1 +#define RB_PWM4_POLAR 0x01 // RW, PWM4 output polarity: 0=default low and high action, 1=default high and low action +#define RB_PWM5_POLAR 0x02 // RW, PWM5 output polarity: 0=default low and high action, 1=default high and low action +#define RB_PWM6_POLAR 0x04 // RW, PWM6 output polarity: 0=default low and high action, 1=default high and low action +#define RB_PWM7_POLAR 0x08 // RW, PWM7 output polarity: 0=default low and high action, 1=default high and low action +#define RB_PWM8_POLAR 0x10 // RW, PWM8 output polarity: 0=default low and high action, 1=default high and low action +#define RB_PWM9_POLAR 0x20 // RW, PWM9 output polarity: 0=default low and high action, 1=default high and low action +#define RB_PWM10_POLAR 0x40 // RW, PWM10 output polarity: 0=default low and high action, 1=default high and low action +#define RB_PWM11_POLAR 0x80 // RW, PWM11 output polarity: 0=default low and high action, 1=default high and low action +#define PWM_CONFIG 2 +#define RB_PWM_CYCLE_SEL 0x01 // RW, PWM cycle selection: 0=256/128/64/32 clocks, 1=255/127/63/31 clocks +#define RB_PWM_STAG_ST 0x02 // RO, PWM stagger cycle status +#define RB_PWM_CYC_MOD 0x0C // RW, PWM data width mode: 00=8 bits data, 01=7 bits data, 10=6 bits data, 11=5 bits data +#define RB_PWM4_5_STAG_EN 0x10 // RW, PWM4/5 stagger output enable: 0=independent output, 1=stagger output +#define RB_PWM6_7_STAG_EN 0x20 // RW, PWM6/7 stagger output enable: 0=independent output, 1=stagger output +#define RB_PWM8_9_STAG_EN 0x40 // RW, PWM8/9 stagger output enable: 0=independent output, 1=stagger output +#define RB_PWM10_11_STAG_EN 0x80 // RW, PWM10/11 stagger output enable: 0=independent output, 1=stagger output +#define PWM_CLOCK_DIV 3 +#define PWM4_DATA_HOLD 4 +#define PWM5_DATA_HOLD 5 +#define PWM6_DATA_HOLD 6 +#define PWM7_DATA_HOLD 7 +#define PWM8_DATA_HOLD 8 +#define PWM9_DATA_HOLD 9 +#define PWM10_DATA_HOLD 10 +#define PWM11_DATA_HOLD 11 + +/* Address space define */ +#define BA_CODE ((PUINT32)0x00000000) // point code base address +#define SZ_CODE 0x00080000 // code size +#define BA_SFR ((PUINT32)0x40000000) // point SFR base address +#define SZ_SFR 0x00010000 // SFR size +#define BA_RAM ((PUINT32)0x20000000) // point RAM base address +#define SZ_RAM 0x00008000 // RAM size + +/* Special Program Space */ +#define DATA_FLASH_ADDR 0x70000 // start address of Data-Flash +#define DATA_FLASH_SIZE 0x8000 // size of Data-Flash +#define BOOT_LOAD_ADDR 0x78000 // start address of boot loader program +#define BOOT_LOAD_SIZE 0x6000 // size of boot loader program +#define BOOT_LOAD_CFG 0x7E000 // start address of configuration information for boot loader program +#define ROM_CFG_ADDR 0x7F000 // chip configuration information address + +/*----- Reference Information --------------------------------------------*/ +#define ID_CH583 0x83 // chip ID +#define ID_CH582 0x82 // chip ID +#define ID_CH581 0x81 // chip ID + +/* Interrupt routine address and interrupt number */ +#define INT_ID_TMR0 16 // interrupt number for Timer0 +#define INT_ID_GPIO_A 17 // interrupt number for GPIO port A +#define INT_ID_GPIO_B 18 // interrupt number for GPIO port B +#define INT_ID_SPI0 19 // interrupt number for SPI0 +#define INT_ID_BLEB 20 // interrupt number for BLEBB +#define INT_ID_BLEL 21 // interrupt number for BLELLE +#define INT_ID_USB 22 // interrupt number for USB +#define INT_ID_USB2 23 // interrupt number for USB2 +#define INT_ID_TMR1 24 // interrupt number for Timer1 +#define INT_ID_TMR2 25 // interrupt number for Timer2 +#define INT_ID_UART0 26 // interrupt number for UART0 +#define INT_ID_UART1 27 // interrupt number for UART1 +#define INT_ID_RTC 28 // interrupt number for RTC +#define INT_ID_ADC 29 // interrupt number for ADC and TouchKey +#define INT_ID_I2C 30 // interrupt number for I2C +#define INT_ID_PWMX_SPI1 31 // interrupt number for PWM4~11 and SPI1 +#define INT_ID_TMR3 32 // interrupt number for Timer3 +#define INT_ID_UART2 33 // interrupt number for UART2 +#define INT_ID_UART3 34 // interrupt number for UART3 +#define INT_ID_WDOG_BAT 35 // interrupt number for Watch-Dog timer and Battery low voltage +#define INT_VEC_ENTRY_SZ 4 // size of each interrupt vector entry +#define INT_ADDR_TMR0 (INT_ID_TMR0*INT_VEC_ENTRY_SZ) // interrupt vector address for Timer0 +#define INT_ADDR_GPIO_A (INT_ID_GPIO_A*INT_VEC_ENTRY_SZ) // interrupt vector address for GPIO port A +#define INT_ADDR_GPIO_B (INT_ID_GPIO_B*INT_VEC_ENTRY_SZ) // interrupt vector address for GPIO port B +#define INT_ADDR_SPI0 (INT_ID_SPI0*INT_VEC_ENTRY_SZ) // interrupt vector address for SPI0 +#define INT_ADDR_BLEB (INT_ID_BLEB*INT_VEC_ENTRY_SZ) // interrupt vector address for BLEBB +#define INT_ADDR_BLEL (INT_ID_BLEL*INT_VEC_ENTRY_SZ) // interrupt vector address for BLELLE +#define INT_ADDR_USB (INT_ID_USB*INT_VEC_ENTRY_SZ) // interrupt vector address for USB +#define INT_ADDR_USB2 (INT_ID_USB2*INT_VEC_ENTRY_SZ) // interrupt vector address for USB2 +#define INT_ADDR_TMR1 (INT_ID_TMR1*INT_VEC_ENTRY_SZ) // interrupt vector address for Timer1 +#define INT_ADDR_TMR2 (INT_ID_TMR2*INT_VEC_ENTRY_SZ) // interrupt vector address for Timer2 +#define INT_ADDR_UART0 (INT_ID_UART0*INT_VEC_ENTRY_SZ) // interrupt vector address for UART0 +#define INT_ADDR_UART1 (INT_ID_UART1*INT_VEC_ENTRY_SZ) // interrupt vector address for UART1 +#define INT_ADDR_RTC (INT_ID_RTC*INT_VEC_ENTRY_SZ) // interrupt vector address for RTC +#define INT_ADDR_ADC (INT_ID_ADC*INT_VEC_ENTRY_SZ) // interrupt vector address for ADC and TouchKey +#define INT_ADDR_I2C (INT_ID_I2C*INT_VEC_ENTRY_SZ) // interrupt vector address for I2C +#define INT_ADDR_PWMX_SPI1 (INT_ID_PWMX_SPI1*INT_VEC_ENTRY_SZ) // interrupt vector address for PWM4~11 and SPI1 +#define INT_ADDR_TMR3 (INT_ID_TMR3*INT_VEC_ENTRY_SZ) // interrupt vector address for Timer3 +#define INT_ADDR_UART2 (INT_ID_UART2*INT_VEC_ENTRY_SZ) // interrupt vector address for UART2 +#define INT_ADDR_UART3 (INT_ID_UART3*INT_VEC_ENTRY_SZ) // interrupt vector address for UART3 +#define INT_ADDR_WDOG_BAT (INT_ID_WDOG_BAT*INT_VEC_ENTRY_SZ) // interrupt vector address for Watch-Dog timer and Battery low voltage + +#ifndef TABLE_IRQN +#define __PFIC_PRIO_BITS 2 /*!< uses 8 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +typedef enum IRQn +{ + Reset_IRQn = 1, + NMI_IRQn = 2, /*!< Non Maskable Interrupt */ + EXC_IRQn = 3, /*!< Exceptions Interrupt */ + SysTick_IRQn = 12, /*!< System timer Interrupt */ + SWI_IRQn = 14, /*!< software Interrupt */ + TMR0_IRQn = 16, + GPIO_A_IRQn = 17, + GPIO_B_IRQn = 18, + SPI0_IRQn = 19, + BLEB_IRQn = 20, + BLEL_IRQn = 21, + USB_IRQn = 22, + USB2_IRQn = 23, + TMR1_IRQn = 24, + TMR2_IRQn = 25, + UART0_IRQn = 26, + UART1_IRQn = 27, + RTC_IRQn = 28, + ADC_IRQn = 29, + I2C_IRQn = 30, + PWMX_SPI1_IRQn = 31, + TMR3_IRQn = 32, + UART2_IRQn = 33, + UART3_IRQn = 34, + WDOG_BAT_IRQn = 35 +} IRQn_Type; +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // __CH583SFR_H__ + + +#ifndef __CH583USBSFR_H__ +#define __CH583USBSFR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************/ +/* Peripheral memory map */ +/******************************************************************************/ +/* usb addresses +// USB: +8000H - 83FFH */ +#define USB_BASE_ADDR (0x40008000) +#define USB2_BASE_ADDR (0x40008400) +#define BA_USB ((PUINT8V)0x40008000) // point USB base address +#define BA_USB2 ((PUINT8V)0x40008400) // point USB2 base address + +/* USB */ +#define R32_USB_CONTROL (*((PUINT32V)0x40008000)) // USB control & interrupt enable & device address +#define R8_USB_CTRL (*((PUINT8V)0x40008000)) // USB base control +#define RB_UC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode +#define RB_UC_LOW_SPEED 0x40 // enable USB low speed: 0=12Mbps, 1=1.5Mbps +#define RB_UC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable +#define RB_UC_SYS_CTRL1 0x20 // USB system control high bit +#define RB_UC_SYS_CTRL0 0x10 // USB system control low bit +#define MASK_UC_SYS_CTRL 0x30 // bit mask of USB system control +// bUC_HOST_MODE & bUC_SYS_CTRL1 & bUC_SYS_CTRL0: USB system control +// 0 00: disable USB device and disable internal pullup resistance +// 0 01: enable USB device and disable internal pullup resistance, need RB_PIN_USB_DP_PU=1 or need external pullup resistance +// 0 1x: enable USB device and enable internal pullup resistance +// 1 00: enable USB host and normal status +// 1 01: enable USB host and force UDP/UDM output SE0 state +// 1 10: enable USB host and force UDP/UDM output J state +// 1 11: enable USB host and force UDP/UDM output resume or K state +#define RB_UC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid +#define RB_UC_RESET_SIE 0x04 // force reset USB SIE, need software clear +#define RB_UC_CLR_ALL 0x02 // force clear FIFO and count of USB +#define RB_UC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB + +#define R8_UDEV_CTRL (*((PUINT8V)0x40008001)) // USB device physical prot control +#define RB_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define RB_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define RB_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define RB_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed +#define RB_UD_GP_BIT 0x02 // general purpose bit +#define RB_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable + +#define R8_UHOST_CTRL R8_UDEV_CTRL // USB host physical prot control +#define RB_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define RB_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define RB_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define RB_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed +#define RB_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset +#define RB_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached + +#define R8_USB_INT_EN (*((PUINT8V)0x40008002)) // USB interrupt enable +#define RB_UIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode +#define RB_UIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode +#define RB_UIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow +#define RB_UIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode +#define RB_UIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event +#define RB_UIE_TRANSFER 0x02 // enable interrupt for USB transfer completion +#define RB_UIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode +#define RB_UIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode + +#define R8_USB_DEV_AD (*((PUINT8V)0x40008003)) // USB device address +#define RB_UDA_GP_BIT 0x80 // general purpose bit +#define MASK_USB_ADDR 0x7F // bit mask for USB device address + +#define R32_USB_STATUS (*((PUINT32V)0x40008004)) // USB miscellaneous status & interrupt flag & interrupt status +#define R8_USB_MIS_ST (*((PUINT8V)0x40008005)) // USB miscellaneous status +#define RB_UMS_SOF_PRES 0x80 // RO, indicate host SOF timer presage status +#define RB_UMS_SOF_ACT 0x40 // RO, indicate host SOF timer action status for USB host +#define RB_UMS_SIE_FREE 0x20 // RO, indicate USB SIE free status +#define RB_UMS_R_FIFO_RDY 0x10 // RO, indicate USB receiving FIFO ready status (not empty) +#define RB_UMS_BUS_RESET 0x08 // RO, indicate USB bus reset status +#define RB_UMS_SUSPEND 0x04 // RO, indicate USB suspend status +#define RB_UMS_DM_LEVEL 0x02 // RO, indicate UDM level saved at device attached to USB host +#define RB_UMS_DEV_ATTACH 0x01 // RO, indicate device attached status on USB host + +#define R8_USB_INT_FG (*((PUINT8V)0x40008006)) // USB interrupt flag +#define RB_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received +#define RB_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK +#define RB_U_SIE_FREE 0x20 // RO, indicate USB SIE free status +#define RB_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear +#define RB_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear +#define RB_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear +#define RB_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear +#define RB_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear +#define RB_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear + +#define R8_USB_INT_ST (*((PUINT8V)0x40008007)) // USB interrupt status +#define RB_UIS_SETUP_ACT 0x80 // RO, indicate SETUP token & 8 bytes setup request received for USB device mode +#define RB_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK +#define RB_UIS_TOKEN1 0x20 // RO, current token PID code bit 1 received for USB device mode +#define RB_UIS_TOKEN0 0x10 // RO, current token PID code bit 0 received for USB device mode +#define MASK_UIS_TOKEN 0x30 // RO, bit mask of current token PID code received for USB device mode +#define UIS_TOKEN_OUT 0x00 +#define UIS_TOKEN_SOF 0x10 +#define UIS_TOKEN_IN 0x20 +#define UIS_TOKEN_SETUP 0x30 +// bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received for USB device mode, keep last status during SETUP token, clear RB_UIF_TRANSFER ( RB_UIF_TRANSFER from 1 to 0 ) to set free +// 00: OUT token PID received +// 01: SOF token PID received +// 10: IN token PID received +// 11: free +#define MASK_UIS_ENDP 0x0F // RO, bit mask of current transfer endpoint number for USB device mode +#define MASK_UIS_H_RES 0x0F // RO, bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received + +#define R8_USB_RX_LEN (*((PUINT8V)0x40008008)) // USB receiving length +#define R32_USB_BUF_MODE (*((PUINT32V)0x4000800C)) // USB endpoint buffer mode +#define R8_UEP4_1_MOD (*((PUINT8V)0x4000800C)) // endpoint 4/1 mode +#define RB_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT) +#define RB_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN) +#define RB_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1 +// bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA +// 0 0 x: disable endpoint and disable buffer +// 1 0 0: 64 bytes buffer for receiving (OUT endpoint) +// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes +// 0 1 0: 64 bytes buffer for transmittal (IN endpoint) +// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes +// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes +// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes +#define RB_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT) +#define RB_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN) +// bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA +// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) +// 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes +// 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes +// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) +// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes + +#define R8_UEP2_3_MOD (*((PUINT8V)0x4000800D)) // endpoint 2/3 mode +#define RB_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT) +#define RB_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN) +#define RB_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3 +#define RB_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT) +#define RB_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN) +#define RB_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2 + +#define R8_UEP567_MOD (*((PUINT8V)0x4000800E)) // endpoint 5/6/7 mode +#define RB_UEP7_RX_EN 0x20 // enable USB endpoint 7 receiving (OUT) +#define RB_UEP7_TX_EN 0x10 // enable USB endpoint 7 transmittal (IN) +#define RB_UEP6_RX_EN 0x08 // enable USB endpoint 6 receiving (OUT) +#define RB_UEP6_TX_EN 0x04 // enable USB endpoint 6 transmittal (IN) +#define RB_UEP5_RX_EN 0x02 // enable USB endpoint 5 receiving (OUT) +#define RB_UEP5_TX_EN 0x01 // enable USB endpoint 5 transmittal (IN) +// bUEPn_RX_EN & bUEPn_TX_EN: USB endpoint 5/6/7 buffer mode, buffer start address is UEPn_DMA +// 0 0: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for receiving (OUT endpoint) +// 0 1: 64 bytes buffer for transmittal (IN endpoint) +// 1 1: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes + +#define R8_UH_EP_MOD R8_UEP2_3_MOD //host endpoint mode +#define RB_UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal +#define RB_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint +// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA +// 0 x: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for transmittal (OUT endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes +#define RB_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving +#define RB_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint +// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA +// 0 x: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for receiving (IN endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes + +#define R16_UEP0_DMA (*((PUINT16V)0x40008010)) // endpoint 0 DMA buffer address +#define R16_UEP1_DMA (*((PUINT16V)0x40008014)) // endpoint 1 DMA buffer address +#define R16_UEP2_DMA (*((PUINT16V)0x40008018)) // endpoint 2 DMA buffer address +#define R16_UH_RX_DMA R16_UEP2_DMA // host rx endpoint buffer address +#define R16_UEP3_DMA (*((PUINT16V)0x4000801C)) // endpoint 3 DMA buffer address +#define R16_UH_TX_DMA R16_UEP3_DMA // host tx endpoint buffer address +#define R16_UEP5_DMA (*((PUINT16V)0x40008054)) // endpoint 5 DMA buffer address +#define R16_UEP6_DMA (*((PUINT16V)0x40008058)) // endpoint 6 DMA buffer address +#define R16_UEP7_DMA (*((PUINT16V)0x4000805C)) // endpoint 7 DMA buffer address +#define R32_USB_EP0_CTRL (*((PUINT32V)0x40008020)) // endpoint 0 control & transmittal length +#define R8_UEP0_T_LEN (*((PUINT8V)0x40008020)) // endpoint 0 transmittal length +#define R8_UEP0_CTRL (*((PUINT8V)0x40008022)) // endpoint 0 control +#define R32_USB_EP1_CTRL (*((PUINT32V)0x40008024)) // endpoint 1 control & transmittal length +#define R8_UEP1_T_LEN (*((PUINT8V)0x40008024)) // endpoint 1 transmittal length +#define R8_UEP1_CTRL (*((PUINT8V)0x40008026)) // endpoint 1 control +#define RB_UEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 +#define RB_UEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 +#define RB_UEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define RB_UEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receiving (OUT) +#define RB_UEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receiving (OUT) +#define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT) +#define UEP_R_RES_ACK 0x00 +#define UEP_R_RES_TOUT 0x04 +#define UEP_R_RES_NAK 0x08 +#define UEP_R_RES_STALL 0x0C +// RB_UEP_R_RES1 & RB_UEP_R_RES0: handshake response type for USB endpoint X receiving (OUT) +// 00: ACK (ready) +// 01: no response, time out to host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +#define RB_UEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN) +#define RB_UEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN) +#define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN) +#define UEP_T_RES_ACK 0x00 +#define UEP_T_RES_TOUT 0x01 +#define UEP_T_RES_NAK 0x02 +#define UEP_T_RES_STALL 0x03 +// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) +// 00: DATA0 or DATA1 then expecting ACK (ready) +// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) + +#define R8_UH_SETUP R8_UEP1_CTRL // host aux setup +#define RB_UH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub +#define RB_UH_SOF_EN 0x40 // USB host automatic SOF enable + +#define R32_USB_EP2_CTRL (*((PUINT32V)0x40008028)) // endpoint 2 control & transmittal length +#define R8_UEP2_T_LEN (*((PUINT8V)0x40008028)) // endpoint 2 transmittal length +#define R8_UEP2_CTRL (*((PUINT8V)0x4000802A)) // endpoint 2 control + +#define R8_UH_EP_PID R8_UEP2_T_LEN // host endpoint and PID +#define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer +#define MASK_UH_ENDP 0x0F // bit mask of endpoint number for USB host transfer + +#define R8_UH_RX_CTRL R8_UEP2_CTRL // host receiver endpoint control +#define RB_UH_R_TOG 0x80 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1 +#define RB_UH_R_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle +#define RB_UH_R_RES 0x04 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions + +#define R32_USB_EP3_CTRL (*((PUINT32V)0x4000802c)) // endpoint 3 control & transmittal length +#define R8_UEP3_T_LEN (*((PUINT8V)0x4000802c)) // endpoint 3 transmittal length +#define R8_UEP3_CTRL (*((PUINT8V)0x4000802e)) // endpoint 3 control +#define R8_UH_TX_LEN R8_UEP3_T_LEN // host transmittal endpoint transmittal length + +#define R8_UH_TX_CTRL R8_UEP3_CTRL // host transmittal endpoint control +#define RB_UH_T_TOG 0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1 +#define RB_UH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle +#define RB_UH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions + +#define R32_USB_EP4_CTRL (*((PUINT32V)0x40008030)) // endpoint 4 control & transmittal length +#define R8_UEP4_T_LEN (*((PUINT8V)0x40008030)) // endpoint 4 transmittal length +#define R8_UEP4_CTRL (*((PUINT8V)0x40008032)) // endpoint 4 control + +#define R32_USB_EP5_CTRL (*((PUINT32V)0x40008064)) // endpoint 5 control & transmittal length +#define R8_UEP5_T_LEN (*((PUINT8V)0x40008064)) // endpoint 5 transmittal length +#define R8_UEP5_CTRL (*((PUINT8V)0x40008066)) // endpoint 5 control + +#define R32_USB_EP6_CTRL (*((PUINT32V)0x40008068)) // endpoint 6 control & transmittal length +#define R8_UEP6_T_LEN (*((PUINT8V)0x40008068)) // endpoint 6 transmittal length +#define R8_UEP6_CTRL (*((PUINT8V)0x4000806A)) // endpoint 6 control + +#define R32_USB_EP7_CTRL (*((PUINT32V)0x4000806C)) // endpoint 7 control & transmittal length +#define R8_UEP7_T_LEN (*((PUINT8V)0x4000806C)) // endpoint 7 transmittal length +#define R8_UEP7_CTRL (*((PUINT8V)0x4000806E)) // endpoint 7 control + +/* USB2 */ +#define R32_USB2_CONTROL (*((PUINT32V)0x40008400)) // USB2 control & interrupt enable & device address +#define R8_USB2_CTRL (*((PUINT8V)0x40008400)) // USB2 base control +#define R8_U2DEV_CTRL (*((PUINT8V)0x40008401)) // USB2 device physical prot control +#define R8_U2HOST_CTRL R8_U2DEV_CTRL // USB2 host physical prot control +#define R8_USB2_INT_EN (*((PUINT8V)0x40008402)) // USB2 interrupt enable +#define R8_USB2_DEV_AD (*((PUINT8V)0x40008403)) // USB2 device address +#define R32_USB2_STATUS (*((PUINT32V)0x40008404)) // USB2 miscellaneous status & interrupt flag & interrupt status +#define R8_USB2_MIS_ST (*((PUINT8V)0x40008405)) // USB2 miscellaneous status +#define R8_USB2_INT_FG (*((PUINT8V)0x40008406)) // USB2 interrupt flag +#define R8_USB2_INT_ST (*((PUINT8V)0x40008407)) // USB2 interrupt status +#define R8_USB2_RX_LEN (*((PUINT8V)0x40008408)) // USB2 receiving length +#define R32_USB2_BUF_MODE (*((PUINT32V)0x4000840C)) // USB2 endpoint buffer mode +#define R8_U2EP4_1_MOD (*((PUINT8V)0x4000840C)) // USB2 endpoint 4/1 mode +#define R8_U2EP2_3_MOD (*((PUINT8V)0x4000840D)) // USB2 endpoint 2/3 mode +#define R8_U2EP567_MOD (*((PUINT8V)0x4000840E)) // USB2 endpoint 5/6/7 mode +#define R8_U2H_EP_MOD R8_U2EP2_3_MOD // USB2 host endpoint mode +#define R16_U2EP0_DMA (*((PUINT16V)0x40008410)) // USB2 endpoint 0 DMA buffer address +#define R16_U2EP1_DMA (*((PUINT16V)0x40008414)) // USB2 endpoint 1 DMA buffer address +#define R16_U2EP2_DMA (*((PUINT16V)0x40008418)) // USB2 endpoint 2 DMA buffer address +#define R16_U2H_RX_DMA R16_U2EP2_DMA // USB2 host rx endpoint buffer address +#define R16_U2EP3_DMA (*((PUINT16V)0x4000841C)) // USB2 endpoint 3 DMA buffer address +#define R16_U2H_TX_DMA R16_U2EP3_DMA // USB2 host tx endpoint buffer address +#define R16_U2EP5_DMA (*((PUINT16V)0x40008454)) // USB2 endpoint 5 DMA buffer address +#define R16_U2EP6_DMA (*((PUINT16V)0x40008458)) // USB2 endpoint 6 DMA buffer address +#define R16_U2EP7_DMA (*((PUINT16V)0x4000845C)) // USB2 endpoint 7 DMA buffer address +#define R32_USB2_EP0_CTRL (*((PUINT32V)0x40008420)) // USB2 endpoint 0 control & transmittal length +#define R8_U2EP0_T_LEN (*((PUINT8V)0x40008420)) // USB2 endpoint 0 transmittal length +#define R8_U2EP0_CTRL (*((PUINT8V)0x40008422)) // USB2 endpoint 0 control +#define R32_USB2_EP1_CTRL (*((PUINT32V)0x40008424)) // USB2 endpoint 1 control & transmittal length +#define R8_U2EP1_T_LEN (*((PUINT8V)0x40008424)) // USB2 endpoint 1 transmittal length +#define R8_U2EP1_CTRL (*((PUINT8V)0x40008426)) // USB2 endpoint 1 control +#define R8_U2H_SETUP R8_U2EP1_CTRL // USB2 host aux setup +#define R32_USB2_EP2_CTRL (*((PUINT32V)0x40008428)) // USB2 endpoint 2 control & transmittal length +#define R8_U2EP2_T_LEN (*((PUINT8V)0x40008428)) // USB2 endpoint 2 transmittal length +#define R8_U2EP2_CTRL (*((PUINT8V)0x4000842A)) // USB2 endpoint 2 control +#define R8_U2H_EP_PID R8_U2EP2_T_LEN // USB2 host endpoint and PID +#define R8_U2H_RX_CTRL R8_U2EP2_CTRL // USB2 host receiver endpoint control +#define R32_USB2_EP3_CTRL (*((PUINT32V)0x4000842c)) // USB2 endpoint 3 control & transmittal length +#define R8_U2EP3_T_LEN (*((PUINT8V)0x4000842c)) // USB2 endpoint 3 transmittal length +#define R8_U2EP3_CTRL (*((PUINT8V)0x4000842e)) // USB2 endpoint 3 control +#define R8_U2H_TX_LEN R8_U2EP3_T_LEN // USB2 host transmittal endpoint transmittal length +#define R8_U2H_TX_CTRL R8_U2EP3_CTRL // USB2 host transmittal endpoint control +#define R32_USB2_EP4_CTRL (*((PUINT32V)0x40008430)) // USB2 endpoint 4 control & transmittal length +#define R8_U2EP4_T_LEN (*((PUINT8V)0x40008430)) // USB2 endpoint 4 transmittal length +#define R8_U2EP4_CTRL (*((PUINT8V)0x40008432)) // USB2 endpoint 4 control +#define R32_USB2_EP5_CTRL (*((PUINT32V)0x40008464)) // USB2 endpoint 5 control & transmittal length +#define R8_U2EP5_T_LEN (*((PUINT8V)0x40008464)) // USB2 endpoint 5 transmittal length +#define R8_U2EP5_CTRL (*((PUINT8V)0x40008466)) // USB2 endpoint 5 control +#define R32_USB2_EP6_CTRL (*((PUINT32V)0x40008468)) // USB2 endpoint 6 control & transmittal length +#define R8_U2EP6_T_LEN (*((PUINT8V)0x40008468)) // USB2 endpoint 6 transmittal length +#define R8_U2EP6_CTRL (*((PUINT8V)0x4000846A)) // USB2 endpoint 6 control +#define R32_USB2_EP7_CTRL (*((PUINT32V)0x4000846C)) // USB2 endpoint 7 control & transmittal length +#define R8_U2EP7_T_LEN (*((PUINT8V)0x4000846C)) // USB2 endpoint 7 transmittal length +#define R8_U2EP7_CTRL (*((PUINT8V)0x4000846E)) // USB2 endpoint 7 control + +#ifdef __cplusplus +} +#endif + +#endif //__CH583USBSFR_H__ + + +#ifndef __USB_TYPE__ +#define __USB_TYPE__ + +#ifdef __cplusplus +extern "C" { +#endif + +/*----- USB constant and structure define --------------------------------*/ + +/* USB PID */ +#ifndef USB_PID_SETUP +#define USB_PID_NULL 0x00 /* reserved PID */ +#define USB_PID_SOF 0x05 +#define USB_PID_SETUP 0x0D +#define USB_PID_IN 0x09 +#define USB_PID_OUT 0x01 +#define USB_PID_ACK 0x02 +#define USB_PID_NAK 0x0A +#define USB_PID_STALL 0x0E +#define USB_PID_DATA0 0x03 +#define USB_PID_DATA1 0x0B +#define USB_PID_PRE 0x0C +#endif + +/* USB standard device request code */ +#ifndef USB_GET_DESCRIPTOR +#define USB_GET_STATUS 0x00 +#define USB_CLEAR_FEATURE 0x01 +#define USB_SET_FEATURE 0x03 +#define USB_SET_ADDRESS 0x05 +#define USB_GET_DESCRIPTOR 0x06 +#define USB_SET_DESCRIPTOR 0x07 +#define USB_GET_CONFIGURATION 0x08 +#define USB_SET_CONFIGURATION 0x09 +#define USB_GET_INTERFACE 0x0A +#define USB_SET_INTERFACE 0x0B +#define USB_SYNCH_FRAME 0x0C +#endif + +/* USB hub class request code */ +#ifndef HUB_GET_DESCRIPTOR +#define HUB_GET_STATUS 0x00 +#define HUB_CLEAR_FEATURE 0x01 +#define HUB_GET_STATE 0x02 +#define HUB_SET_FEATURE 0x03 +#define HUB_GET_DESCRIPTOR 0x06 +#define HUB_SET_DESCRIPTOR 0x07 +#endif + +/* USB HID class request code */ +#ifndef HID_GET_REPORT +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#endif + +/* Bit define for USB request type */ +#ifndef USB_REQ_TYP_MASK +#define USB_REQ_TYP_IN 0x80 /* control IN, device to host */ +#define USB_REQ_TYP_OUT 0x00 /* control OUT, host to device */ +#define USB_REQ_TYP_READ 0x80 /* control read, device to host */ +#define USB_REQ_TYP_WRITE 0x00 /* control write, host to device */ +#define USB_REQ_TYP_MASK 0x60 /* bit mask of request type */ +#define USB_REQ_TYP_STANDARD 0x00 +#define USB_REQ_TYP_CLASS 0x20 +#define USB_REQ_TYP_VENDOR 0x40 +#define USB_REQ_TYP_RESERVED 0x60 +#define USB_REQ_RECIP_MASK 0x1F /* bit mask of request recipient */ +#define USB_REQ_RECIP_DEVICE 0x00 +#define USB_REQ_RECIP_INTERF 0x01 +#define USB_REQ_RECIP_ENDP 0x02 +#define USB_REQ_RECIP_OTHER 0x03 +#endif + +/* USB request type for hub class request */ +#ifndef HUB_GET_HUB_DESCRIPTOR +#define HUB_CLEAR_HUB_FEATURE 0x20 +#define HUB_CLEAR_PORT_FEATURE 0x23 +#define HUB_GET_BUS_STATE 0xA3 +#define HUB_GET_HUB_DESCRIPTOR 0xA0 +#define HUB_GET_HUB_STATUS 0xA0 +#define HUB_GET_PORT_STATUS 0xA3 +#define HUB_SET_HUB_DESCRIPTOR 0x20 +#define HUB_SET_HUB_FEATURE 0x20 +#define HUB_SET_PORT_FEATURE 0x23 +#endif + +/* Hub class feature selectors */ +#ifndef HUB_PORT_RESET +#define HUB_C_HUB_LOCAL_POWER 0 +#define HUB_C_HUB_OVER_CURRENT 1 +#define HUB_PORT_CONNECTION 0 +#define HUB_PORT_ENABLE 1 +#define HUB_PORT_SUSPEND 2 +#define HUB_PORT_OVER_CURRENT 3 +#define HUB_PORT_RESET 4 +#define HUB_PORT_POWER 8 +#define HUB_PORT_LOW_SPEED 9 +#define HUB_C_PORT_CONNECTION 16 +#define HUB_C_PORT_ENABLE 17 +#define HUB_C_PORT_SUSPEND 18 +#define HUB_C_PORT_OVER_CURRENT 19 +#define HUB_C_PORT_RESET 20 +#endif + +/* USB descriptor type */ +#ifndef USB_DESCR_TYP_DEVICE +#define USB_DESCR_TYP_DEVICE 0x01 +#define USB_DESCR_TYP_CONFIG 0x02 +#define USB_DESCR_TYP_STRING 0x03 +#define USB_DESCR_TYP_INTERF 0x04 +#define USB_DESCR_TYP_ENDP 0x05 +#define USB_DESCR_TYP_QUALIF 0x06 +#define USB_DESCR_TYP_SPEED 0x07 +#define USB_DESCR_TYP_OTG 0x09 +#define USB_DESCR_TYP_HID 0x21 +#define USB_DESCR_TYP_REPORT 0x22 +#define USB_DESCR_TYP_PHYSIC 0x23 +#define USB_DESCR_TYP_CS_INTF 0x24 +#define USB_DESCR_TYP_CS_ENDP 0x25 +#define USB_DESCR_TYP_HUB 0x29 +#endif + +/* USB device class */ +#ifndef USB_DEV_CLASS_HUB +#define USB_DEV_CLASS_RESERVED 0x00 +#define USB_DEV_CLASS_AUDIO 0x01 +#define USB_DEV_CLASS_COMMUNIC 0x02 +#define USB_DEV_CLASS_HID 0x03 +#define USB_DEV_CLASS_MONITOR 0x04 +#define USB_DEV_CLASS_PHYSIC_IF 0x05 +#define USB_DEV_CLASS_POWER 0x06 +#define USB_DEV_CLASS_PRINTER 0x07 +#define USB_DEV_CLASS_STORAGE 0x08 +#define USB_DEV_CLASS_HUB 0x09 +#define USB_DEV_CLASS_VEN_SPEC 0xFF +#endif + +/* USB endpoint type and attributes */ +#ifndef USB_ENDP_TYPE_MASK +#define USB_ENDP_DIR_MASK 0x80 +#define USB_ENDP_ADDR_MASK 0x0F +#define USB_ENDP_TYPE_MASK 0x03 +#define USB_ENDP_TYPE_CTRL 0x00 +#define USB_ENDP_TYPE_ISOCH 0x01 +#define USB_ENDP_TYPE_BULK 0x02 +#define USB_ENDP_TYPE_INTER 0x03 +#endif + +#ifndef USB_DEVICE_ADDR +#define USB_DEVICE_ADDR 0x02 /* ĬϵUSB豸ַ */ +#endif +#ifndef DEFAULT_ENDP0_SIZE +#define DEFAULT_ENDP0_SIZE 8 /* default maximum packet size for endpoint 0 */ +#endif +#ifndef MAX_PACKET_SIZE +#define MAX_PACKET_SIZE 64 /* maximum packet size */ +#endif +#ifndef USB_BO_CBW_SIZE +#define USB_BO_CBW_SIZE 0x1F /* CBWܳ */ +#define USB_BO_CSW_SIZE 0x0D /* ״̬CSWܳ */ +#endif +#ifndef USB_BO_CBW_SIG +#define USB_BO_CBW_SIG 0x43425355 /* CBWʶ־'USBC' */ +#define USB_BO_CSW_SIG 0x53425355 /* ״̬CSWʶ־'USBS' */ +#endif + +#ifndef __PACKED +#define __PACKED __attribute__((packed)) +#endif + +typedef struct __PACKED _USB_SETUP_REQ { + UINT8 bRequestType; + UINT8 bRequest; + UINT16 wValue; + UINT16 wIndex; + UINT16 wLength; +} USB_SETUP_REQ, *PUSB_SETUP_REQ; + +typedef struct __PACKED _USB_DEVICE_DESCR { + UINT8 bLength; + UINT8 bDescriptorType; + UINT16 bcdUSB; + UINT8 bDeviceClass; + UINT8 bDeviceSubClass; + UINT8 bDeviceProtocol; + UINT8 bMaxPacketSize0; + UINT16 idVendor; + UINT16 idProduct; + UINT16 bcdDevice; + UINT8 iManufacturer; + UINT8 iProduct; + UINT8 iSerialNumber; + UINT8 bNumConfigurations; +} USB_DEV_DESCR, *PUSB_DEV_DESCR; + +typedef struct __PACKED _USB_CONFIG_DESCR { + UINT8 bLength; + UINT8 bDescriptorType; + UINT16 wTotalLength; + UINT8 bNumInterfaces; + UINT8 bConfigurationValue; + UINT8 iConfiguration; + UINT8 bmAttributes; + UINT8 MaxPower; +} USB_CFG_DESCR, *PUSB_CFG_DESCR; + +typedef struct __PACKED _USB_INTERF_DESCR { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bInterfaceNumber; + UINT8 bAlternateSetting; + UINT8 bNumEndpoints; + UINT8 bInterfaceClass; + UINT8 bInterfaceSubClass; + UINT8 bInterfaceProtocol; + UINT8 iInterface; +} USB_ITF_DESCR, *PUSB_ITF_DESCR; + +typedef struct __PACKED _USB_ENDPOINT_DESCR { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bEndpointAddress; + UINT8 bmAttributes; + UINT16 wMaxPacketSize; + UINT8 bInterval; +} USB_ENDP_DESCR, *PUSB_ENDP_DESCR; + +typedef struct __PACKED _USB_CONFIG_DESCR_LONG { + USB_CFG_DESCR cfg_descr; + USB_ITF_DESCR itf_descr; + USB_ENDP_DESCR endp_descr[1]; +} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG; + +typedef USB_CFG_DESCR_LONG *PXUSB_CFG_DESCR_LONG; + +typedef struct __PACKED _USB_HUB_DESCR { + UINT8 bDescLength; + UINT8 bDescriptorType; + UINT8 bNbrPorts; + UINT8 wHubCharacteristicsL; + UINT8 wHubCharacteristicsH; + UINT8 bPwrOn2PwrGood; + UINT8 bHubContrCurrent; + UINT8 DeviceRemovable; + UINT8 PortPwrCtrlMask; +} USB_HUB_DESCR, *PUSB_HUB_DESCR; + +typedef USB_HUB_DESCR *PXUSB_HUB_DESCR; + +typedef struct __PACKED _USB_HID_DESCR { + UINT8 bLength; + UINT8 bDescriptorType; + UINT16 bcdHID; + UINT8 bCountryCode; + UINT8 bNumDescriptors; + UINT8 bDescriptorTypeX; + UINT8 wDescriptorLengthL; + UINT8 wDescriptorLengthH; +} USB_HID_DESCR, *PUSB_HID_DESCR; + +typedef USB_HID_DESCR *PXUSB_HID_DESCR; + +typedef struct __PACKED _UDISK_BOC_CBW { /* command of BulkOnly USB-FlashDisk */ + UINT32 mCBW_Sig; + UINT32 mCBW_Tag; + UINT32 mCBW_DataLen; /* uppest byte of data length, always is 0 */ + UINT8 mCBW_Flag; /* transfer direction and etc. */ + UINT8 mCBW_LUN; + UINT8 mCBW_CB_Len; /* length of command block */ + UINT8 mCBW_CB_Buf[16]; /* command block buffer */ +} UDISK_BOC_CBW, *PUDISK_BOC_CBW; + +typedef UDISK_BOC_CBW *PXUDISK_BOC_CBW; + +typedef struct __PACKED _UDISK_BOC_CSW { /* status of BulkOnly USB-FlashDisk */ + UINT32 mCSW_Sig; + UINT32 mCSW_Tag; + UINT32 mCSW_Residue; /* return: remainder bytes */ + UINT8 mCSW_Status; /* return: result status */ +} UDISK_BOC_CSW, *PUDISK_BOC_CSW; + +typedef UDISK_BOC_CSW *PXUDISK_BOC_CSW; + +#ifdef __cplusplus +} +#endif + +#endif // __USB_TYPE__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_adc.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_adc.h new file mode 100644 index 0000000..0654a5e --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_adc.h @@ -0,0 +1,265 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_adc.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_ADC_H__ +#define __CH58x_ADC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ROM_CFG_TMP_25C 0x7F014 + +/** + * @brief adc single channel define + */ +typedef enum +{ + CH_EXTIN_0 = 0, // ADC ⲿģͨ 0 + CH_EXTIN_1, // ADC ⲿģͨ 1 + CH_EXTIN_2, // ADC ⲿģͨ 2 + CH_EXTIN_3, // ADC ⲿģͨ 3 + CH_EXTIN_4, // ADC ⲿģͨ 4 + CH_EXTIN_5, // ADC ⲿģͨ 5 + CH_EXTIN_6, // ADC ⲿģͨ 6 + CH_EXTIN_7, // ADC ⲿģͨ 7 + CH_EXTIN_8, // ADC ⲿģͨ 8 + CH_EXTIN_9, // ADC ⲿģͨ 9 + CH_EXTIN_10, // ADC ⲿģͨ 10 + CH_EXTIN_11, // ADC ⲿģͨ 11 + CH_EXTIN_12, // ADC ⲿģͨ 12 + CH_EXTIN_13, // ADC ⲿģͨ 13 + + CH_INTE_VBAT = 14, // ADC ڲؼͨ + CH_INTE_VTEMP = 15, // ADC ڲ¶ȴͨ + +} ADC_SingleChannelTypeDef; + +/** + * @brief adc differential channel define + */ +typedef enum +{ + CH_DIFF_0_2 = 0, // ADC ͨ #0-#2 + CH_DIFF_1_3, // ADC ͨ #1-#3 + +} ADC_DiffChannelTypeDef; + +/** + * @brief adc sampling clock + */ +typedef enum +{ + SampleFreq_3_2 = 0, // 3.2M Ƶ + SampleFreq_8, // 8M Ƶ + SampleFreq_5_33, // 5.33M Ƶ + SampleFreq_4, // 4M Ƶ +} ADC_SampClkTypeDef; + +/** + * @brief adc signal PGA + */ +typedef enum +{ + ADC_PGA_1_4 = 0, // -12dB, 1/4 + ADC_PGA_1_2, // -6dB, 1/2 + ADC_PGA_0, // 0dB, 1 + ADC_PGA_2, // 6dB, 2 +} ADC_SignalPGATypeDef; + +/** + * @brief Configuration DMA mode + */ +typedef enum +{ + ADC_Mode_Single = 0, // ģʽ + ADC_Mode_LOOP, // ѭģʽ +} ADC_DMAModeTypeDef; + + +/** + * @brief ADC ͨ + * + * @param d - refer to ADC_SingleChannelTypeDef + */ +#define ADC_ChannelCfg(d) (R8_ADC_CHANNEL = d) + +/** + * @brief ADC ʱ + * + * @param d - refer to ADC_SampClkTypeDef + */ +#define ADC_SampClkCfg(d) (R8_ADC_CFG = R8_ADC_CFG & (~RB_ADC_CLK_DIV) | (d << 6)) + +/** + * @brief ADC ź + * + * @param d - refer to ADC_SignalPGATypeDef + */ +#define ADC_PGACfg(d) (R8_ADC_CFG = R8_ADC_CFG & (~RB_ADC_PGA_GAIN) | (d << 4)) + +/** + * @brief ڲ¶ȴУ׼ֵ + * + * @param d - У׼ֵ + */ +#define ADC_TempCalibCfg(d) (R8_TEM_SENSOR = R8_TEM_SENSOR & (~RB_TEM_SEN_CALIB) | d) + +/** + * @brief ⲿźŵͨʼ + * + * @param sp - refer to ADC_SampClkTypeDef + * @param ga - refer to ADC_SignalPGATypeDef + */ +void ADC_ExtSingleChSampInit(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga); + +/** + * @brief ⲿźŲͨʼ + * + * @param sp - refer to ADC_SampClkTypeDef + * @param ga - refer to ADC_SignalPGATypeDef + */ +void ADC_ExtDiffChSampInit(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga); + +/** + * @brief ͨʼ + */ +void TouchKey_ChSampInit(void); + +/** + * @brief رTouchKeyԴ + */ +#define TouchKey_DisableTSPower() (R8_TKEY_CFG &= ~RB_TKEY_PWR_ON) + +/** + * @brief ¶ȴʼ + */ +void ADC_InterTSSampInit(void); + +/** + * @brief ر¶ȴԴ + */ +#define ADC_DisableTSPower() (R8_TEM_SENSOR = 0) + +/** + * @brief õصѹʼ + */ +void ADC_InterBATSampInit(void); + +/** + * @brief ADCִеת + * + * @return ADCת + */ +uint16_t ADC_ExcutSingleConver(void); + +/** + * @brief ݴֵ,ȡƫֵ,ADCô˺ȡУ׼ֵ + * + * @return ƫ + */ +signed short ADC_DataCalib_Rough(void); + +/** + * @brief TouchKeyת + * + * @param charg - Touchkeyʱ,5bitsЧ, t=charg*Tadc + * @param disch - Touchkeyŵʱ,3bitsЧ, t=disch*Tadc + * + * @return ǰTouchKeyЧ + */ +uint16_t TouchKey_ExcutSingleConver(uint8_t charg, uint8_t disch); + +/** + * @brief ADC + * + * @param cycle - λΪ 16ϵͳʱ + */ +void ADC_AutoConverCycle(uint8_t cycle); + +/** + * @brief DMA + * + * @param s - ǷDMA + * @param startAddr - DMA ʼַ + * @param endAddr - DMA ַ + * @param m - DMAģʽ + */ +void ADC_DMACfg(uint8_t s, uint16_t startAddr, uint16_t endAddr, ADC_DMAModeTypeDef m); + +/** + * @brief Convert ADC value to temperature(Celsius) + * + * @param adc_val - adc value + * + * @return temperature (Celsius) + */ +int adc_to_temperature_celsius(uint16_t adc_val); + +/** + * @brief ȡADCתֵ + * + * @return ADCתֵ + */ +#define ADC_ReadConverValue() (R16_ADC_DATA) + +/** + * @brief ADCִеת + */ +#define ADC_StartUp() (R8_ADC_CONVERT = RB_ADC_START) + +/** + * @brief ȡADCж״̬ + */ +#define ADC_GetITStatus() (R8_ADC_INT_FLAG & RB_ADC_IF_EOC) + +/** + * @brief ADCжϱ־ + */ +#define ADC_ClearITFlag() (R8_ADC_CONVERT = 0) + +/** + * @brief ȡADC DMA״̬ + */ +#define ADC_GetDMAStatus() (R8_ADC_DMA_IF & RB_ADC_IF_DMA_END) + +/** + * @brief ADC DMAɱ־ + */ +#define ADC_ClearDMAFlag() (R8_ADC_DMA_IF |= RB_ADC_IF_DMA_END) + +/** + * @brief Զ ADC + */ +#define ADC_StartDMA() (R8_ADC_CTRL_DMA |= RB_ADC_AUTO_EN) + +/** + * @brief ֹͣԶ ADC + */ +#define ADC_StopDMA() (R8_ADC_CTRL_DMA &= ~RB_ADC_AUTO_EN) + +/** + * @brief ȡTouchKeyж״̬ + */ +#define TouchKey_GetITStatus() (R8_ADC_INT_FLAG & RB_ADC_IF_EOC) + +/** + * @brief TouchKeyжϱ־ + */ +#define TouchKey_ClearITFlag() (R8_TKEY_CTRL |= RB_TKEY_PWR_ON) + + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_ADC_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_clk.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_clk.h new file mode 100644 index 0000000..ed1984d --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_clk.h @@ -0,0 +1,290 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_clk.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_CLK_H__ +#define __CH58x_CLK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief ϵͳƵ + */ +typedef enum +{ + CLK_SOURCE_LSI = 0x00, + CLK_SOURCE_LSE, + + CLK_SOURCE_HSE_16MHz = 0x22, + CLK_SOURCE_HSE_8MHz = 0x24, + CLK_SOURCE_HSE_6_4MHz = 0x25, + CLK_SOURCE_HSE_4MHz = 0x28, + CLK_SOURCE_HSE_2MHz = (0x20 | 16), + CLK_SOURCE_HSE_1MHz = (0x20 | 0), + + CLK_SOURCE_PLL_80MHz = 0x46, + CLK_SOURCE_PLL_60MHz = 0x48, + CLK_SOURCE_PLL_48MHz = (0x40 | 10), + CLK_SOURCE_PLL_40MHz = (0x40 | 12), + CLK_SOURCE_PLL_36_9MHz = (0x40 | 13), + CLK_SOURCE_PLL_32MHz = (0x40 | 15), + CLK_SOURCE_PLL_30MHz = (0x40 | 16), + CLK_SOURCE_PLL_24MHz = (0x40 | 20), + CLK_SOURCE_PLL_20MHz = (0x40 | 24), + CLK_SOURCE_PLL_15MHz = (0x40 | 0), +} SYS_CLKTypeDef; + +/** + * @brief 32Kʱѡ + */ +typedef enum +{ + Clk32K_LSI = 0, + Clk32K_LSE, + +} LClk32KTypeDef; + +/** + * @brief 32Mλ + */ +typedef enum +{ + HSE_RCur_75 = 0, + HSE_RCur_100, + HSE_RCur_125, + HSE_RCur_150 + +} HSECurrentTypeDef; + +/** + * @brief 32Mڲݵλ + */ +typedef enum +{ + HSECap_10p = 0, + HSECap_12p, + HSECap_14p, + HSECap_16p, + HSECap_18p, + HSECap_20p, + HSECap_22p, + HSECap_24p + +} HSECapTypeDef; + +/** + * @brief 32Kλ + */ +typedef enum +{ + LSE_RCur_70 = 0, + LSE_RCur_100, + LSE_RCur_140, + LSE_RCur_200 + +} LSECurrentTypeDef; + +/** + * @brief 32Kڲݵλ + */ +typedef enum +{ + LSECap_2p = 0, + LSECap_13p, + LSECap_14p, + LSECap_15p, + LSECap_16p, + LSECap_17p, + LSECap_18p, + LSECap_19p, + LSECap_20p, + LSECap_21p, + LSECap_22p, + LSECap_23p, + LSECap_24p, + LSECap_25p, + LSECap_26p, + LSECap_27p + +} LSECapTypeDef; + +#define MAX_DAY 0x00004000 +#define MAX_2_SEC 0x0000A8C0 +//#define MAX_SEC 0x545FFFFF + +#define BEGYEAR 2020 +#define IsLeapYear(yr) (!((yr) % 400) || (((yr) % 100) && !((yr) % 4))) +#define YearLength(yr) (IsLeapYear(yr) ? 366 : 365) +#define monthLength(lpyr, mon) (((mon) == 1) ? (28 + (lpyr)) : (((mon) > 6) ? (((mon) & 1) ? 31 : 30) : (((mon) & 1) ? 30 : 31))) + +/** + * @brief rtc timer mode period define + */ +typedef enum +{ + Period_0_125_S = 0, // 0.125s + Period_0_25_S, // 0.25s + Period_0_5_S, // 0.5s + Period_1_S, // 1s + Period_2_S, // 2s + Period_4_S, // 4s + Period_8_S, // 8s + Period_16_S, // 16s +} RTC_TMRCycTypeDef; + +/** + * @brief rtc interrupt event define + */ +typedef enum +{ + RTC_TRIG_EVENT = 0, // RTC ¼ + RTC_TMR_EVENT, // RTC ڶʱ¼ + +} RTC_EVENTTypeDef; + +/** + * @brief rtc interrupt event define + */ +typedef enum +{ + RTC_TRIG_MODE = 0, // RTC ģʽ + RTC_TMR_MODE, // RTC ڶʱģʽ + +} RTC_MODETypeDef; + +typedef enum +{ + /* У׼ԽߣʱԽ */ + Level_32 = 3, // ʱ 1.2ms 1000ppm (32M Ƶ) 1100ppm (60M Ƶ) + Level_64, // ʱ 2.2ms 800ppm (32M Ƶ) 1000ppm (60M Ƶ) + Level_128, // ʱ 4.2ms 600ppm (32M Ƶ) 800ppm (60M Ƶ) + +} Cali_LevelTypeDef; + +/** + * @brief 32K ƵʱԴ + * + * @param hc - ѡ32Kʹڲⲿ + */ +void LClk32K_Select(LClk32KTypeDef hc); + +/** + * @brief HSE ƫõ + * + * @param c - 75%,100%,125%,150% + */ +void HSECFG_Current(HSECurrentTypeDef c); + +/** + * @brief HSE ص + * + * @param c - refer to HSECapTypeDef + */ +void HSECFG_Capacitance(HSECapTypeDef c); + +/** + * @brief LSE ƫõ + * + * @param c - 70%,100%,140%,200% + */ +void LSECFG_Current(LSECurrentTypeDef c); + +/** + * @brief LSE ص + * + * @param c - refer to LSECapTypeDef + */ +void LSECFG_Capacitance(LSECapTypeDef c); + +void Calibration_LSI(Cali_LevelTypeDef cali_Lv); /* ƵУ׼ڲ32Kʱ */ + +/** + * @brief RTCʱӳʼǰʱ + * + * @param y - ꣬MAX_Y = BEGYEAR + 44 + * @param mon - £MAX_MON = 12 + * @param d - գMAX_D = 31 + * @param h - СʱMAX_H = 23 + * @param m - ÷ӣMAX_M = 59 + * @param s - 룬MAX_S = 59 + */ +void RTC_InitTime(uint16_t y, uint16_t mon, uint16_t d, uint16_t h, uint16_t m, uint16_t s); + +/** + * @brief ȡǰʱ + * + * @param py - ȡ꣬MAX_Y = BEGYEAR + 44 + * @param pmon - ȡ£MAX_MON = 12 + * @param pd - ȡգMAX_D = 31 + * @param ph - ȡСʱMAX_H = 23 + * @param pm - ȡķӣMAX_M = 59 + * @param ps - ȡ룬MAX_S = 59 + */ +void RTC_GetTime(uint16_t *py, uint16_t *pmon, uint16_t *pd, uint16_t *ph, uint16_t *pm, uint16_t *ps); + +/** + * @brief LSE/LSIʱӣõǰRTC + * + * @param cyc - ڼֵMAX_CYC = 0xA8BFFFFF = 2831155199 + */ +void RTC_SetCycle32k(uint32_t cyc); + +/** + * @brief LSE/LSIʱӣȡǰRTC + * + * @return ǰMAX_CYC = 0xA8BFFFFF = 2831155199 + */ +uint32_t RTC_GetCycle32k(void); + +/** + * @brief RTCʱģʽãעⶨʱ׼̶Ϊ32768Hz + * + * @param t - refer to RTC_TMRCycTypeDef + */ +void RTC_TRIGFunCfg(uint32_t cyc); + +/** + * @brief RTCʱģʽãעⶨʱ׼̶Ϊ32768Hz + * + * @param t - refer to RTC_TMRCycTypeDef + */ +void RTC_TMRFunCfg(RTC_TMRCycTypeDef t); + +/** + * @brief RTC ģʽܹر + * + * @param m - Ҫرյĵǰģʽ + */ +void RTC_ModeFunDisable(RTC_MODETypeDef m); + +/** + * @brief ȡRTCжϱ־ + * + * @param f - refer to RTC_EVENTTypeDef + * + * @return жϱ־״̬ + */ +uint8_t RTC_GetITFlag(RTC_EVENTTypeDef f); + +/** + * @brief RTCжϱ־ + * + * @param f - refer to RTC_EVENTTypeDef + */ +void RTC_ClearITFlag(RTC_EVENTTypeDef f); + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_CLK_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_common.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_common.h new file mode 100644 index 0000000..b51fe14 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_common.h @@ -0,0 +1,91 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_common.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + + +#ifndef __CH58x_COMM_H__ +#define __CH58x_COMM_H__ + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifndef NULL +#define NULL 0 +#endif +#define ALL 0xFFFF + +#ifndef __HIGH_CODE +#define __HIGH_CODE __attribute__((section(".highcode"))) +#endif + +#ifndef __INTERRUPT +#ifdef INT_SOFT +#define __INTERRUPT __attribute__((interrupt())) +#else +#define __INTERRUPT __attribute__((interrupt("WCH-Interrupt-fast"))) +#endif +#endif + +/** + * @brief ϵͳƵʱӣHz + */ +#ifndef FREQ_SYS +#define FREQ_SYS 60000000 +#endif + +#ifndef SAFEOPERATE +#define SAFEOPERATE __nop();__nop() +#endif + +/** + * @brief 32KʱӣHz + */ +#ifdef CLK_OSC32K +#if ( CLK_OSC32K == 1 ) +#define CAB_LSIFQ 32000 +#else +#define CAB_LSIFQ 32768 +#endif +#else +#define CAB_LSIFQ 32000 +#endif + +#include +#include +#include "CH583SFR.h" +#include "core_riscv.h" +#include "CH58x_clk.h" +#include "CH58x_uart.h" +#include "CH58x_gpio.h" +#include "CH58x_i2c.h" +#include "CH58x_flash.h" +#include "CH58x_pwr.h" +#include "CH58x_pwm.h" +#include "CH58x_adc.h" +#include "CH58x_sys.h" +#include "CH58x_timer.h" +#include "CH58x_spi.h" +#include "CH58x_usbhost.h" +#include "ISP583.h" + + +#define DelayMs(x) mDelaymS(x) +#define DelayUs(x) mDelayuS(x) + + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_COMM_H__ + diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_flash.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_flash.h new file mode 100644 index 0000000..bfbe28c --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_flash.h @@ -0,0 +1,42 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_flash.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_FLASH_H__ +#define __CH58x_FLASH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief ȡFlash-ROM + * + * @param StartAddr - read address + * @param Buffer - read buffer + * @param len - read len + */ +void FLASH_ROM_READ(uint32_t StartAddr, void *Buffer, uint32_t len); + +void FLASH_ROM_READ(UINT32 StartAddr, PVOID Buffer, UINT32 len); /* ȡFlash-ROM */ + +UINT8 UserOptionByteConfig(FunctionalState RESET_EN, FunctionalState BOOT_PIN, FunctionalState UART_NO_KEY_EN, + UINT32 FLASHProt_Size); + +UINT8 UserOptionByteClose_SWD(void); + +void UserOptionByte_Active(void); + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_FLASH_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_gpio.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_gpio.h new file mode 100644 index 0000000..f5072ce --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_gpio.h @@ -0,0 +1,274 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_gpio.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_GPIO_H__ +#define __CH58x_GPIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief GPIO_pins_define + */ +#define GPIO_Pin_0 (0x00000001) /*!< Pin 0 selected */ +#define GPIO_Pin_1 (0x00000002) /*!< Pin 1 selected */ +#define GPIO_Pin_2 (0x00000004) /*!< Pin 2 selected */ +#define GPIO_Pin_3 (0x00000008) /*!< Pin 3 selected */ +#define GPIO_Pin_4 (0x00000010) /*!< Pin 4 selected */ +#define GPIO_Pin_5 (0x00000020) /*!< Pin 5 selected */ +#define GPIO_Pin_6 (0x00000040) /*!< Pin 6 selected */ +#define GPIO_Pin_7 (0x00000080) /*!< Pin 7 selected */ +#define GPIO_Pin_8 (0x00000100) /*!< Pin 8 selected */ +#define GPIO_Pin_9 (0x00000200) /*!< Pin 9 selected */ +#define GPIO_Pin_10 (0x00000400) /*!< Pin 10 selected */ +#define GPIO_Pin_11 (0x00000800) /*!< Pin 11 selected */ +#define GPIO_Pin_12 (0x00001000) /*!< Pin 12 selected */ +#define GPIO_Pin_13 (0x00002000) /*!< Pin 13 selected */ +#define GPIO_Pin_14 (0x00004000) /*!< Pin 14 selected */ +#define GPIO_Pin_15 (0x00008000) /*!< Pin 15 selected */ +#define GPIO_Pin_16 (0x00010000) /*!< Pin 16 selected */ +#define GPIO_Pin_17 (0x00020000) /*!< Pin 17 selected */ +#define GPIO_Pin_18 (0x00040000) /*!< Pin 18 selected */ +#define GPIO_Pin_19 (0x00080000) /*!< Pin 19 selected */ +#define GPIO_Pin_20 (0x00100000) /*!< Pin 20 selected */ +#define GPIO_Pin_21 (0x00200000) /*!< Pin 21 selected */ +#define GPIO_Pin_22 (0x00400000) /*!< Pin 22 selected */ +#define GPIO_Pin_23 (0x00800000) /*!< Pin 23 selected */ +#define GPIO_Pin_All (0xFFFFFFFF) /*!< All pins selected */ + +/** + * @brief Configuration GPIO Mode + */ +typedef enum +{ + GPIO_ModeIN_Floating, // + GPIO_ModeIN_PU, // + GPIO_ModeIN_PD, // + GPIO_ModeOut_PP_5mA, //5mA + GPIO_ModeOut_PP_20mA, //20mA + +} GPIOModeTypeDef; + +/** + * @brief Configuration GPIO IT Mode + */ +typedef enum +{ + GPIO_ITMode_LowLevel, //͵ƽ + GPIO_ITMode_HighLevel, //ߵƽ + GPIO_ITMode_FallEdge, //½ش + GPIO_ITMode_RiseEdge, //ش + +} GPIOITModeTpDef; + +/** + * @brief GPIOA˿ģʽ + * + * @param pin - PA0-PA15 + * @param mode - + */ +void GPIOA_ModeCfg(uint32_t pin, GPIOModeTypeDef mode); + +/** + * @brief GPIOB˿ģʽ + * + * @param pin - PB0-PB23 + * @param mode - + */ +void GPIOB_ModeCfg(uint32_t pin, GPIOModeTypeDef mode); + +/** + * @brief GPIOA˿õ + * + * @param pin - PA0-PA15 + */ +#define GPIOA_ResetBits(pin) (R32_PA_CLR |= pin) + +/** + * @brief GPIOA˿ø + * + * @param pin - PA0-PA15 + */ +#define GPIOA_SetBits(pin) (R32_PA_OUT |= pin) + +/** + * @brief GPIOB˿õ + * + * @param pin - PB0-PB23 + */ +#define GPIOB_ResetBits(pin) (R32_PB_CLR |= pin) + +/** + * @brief GPIOB˿ø + * + * @param pin - PB0-PB23 + */ +#define GPIOB_SetBits(pin) (R32_PB_OUT |= pin) + +/** + * @brief GPIOA˿ƽת + * + * @param pin - PA0-PA15 + */ +#define GPIOA_InverseBits(pin) (R32_PA_OUT ^= pin) + +/** + * @brief GPIOB˿ƽת + * + * @param pin - PB0-PB23 + */ +#define GPIOB_InverseBits(pin) (R32_PB_OUT ^= pin) + +/** + * @brief GPIOA˿32λݷأ16λЧ + * + * @return GPIOA˿32λ + */ +#define GPIOA_ReadPort() (R32_PA_PIN) + +/** + * @brief GPIOB˿32λݷأ24λЧ + * + * @return GPIOB˿32λ + */ +#define GPIOB_ReadPort() (R32_PB_PIN) + +/** + * @brief GPIOA˿״̬0-ŵ͵ƽ(!0)-Ÿߵƽ + * + * @param pin - PA0-PA15 + * + * @return GPIOA˿״̬ + */ +#define GPIOA_ReadPortPin(pin) (R32_PA_PIN & (pin)) + +/** + * @brief GPIOB˿״̬0-ŵ͵ƽ(!0)-Ÿߵƽ + * + * @param pin - PB0-PB23 + * + * @return GPIOB˿״̬ + */ +#define GPIOB_ReadPortPin(pin) (R32_PB_PIN & (pin)) + +/** + * @brief GPIOAжģʽ + * + * @param pin - PA0-PA15 + * @param mode - + */ +void GPIOA_ITModeCfg(uint32_t pin, GPIOITModeTpDef mode); + +/** + * @brief GPIOBжģʽ + * + * @param pin - PB0-PB23 + * @param mode - + */ +void GPIOB_ITModeCfg(uint32_t pin, GPIOITModeTpDef mode); + +/** + * @brief ȡGPIOA˿жϱ־״̬ + * + * @return GPIOA˿жϱ־״̬ + */ +#define GPIOA_ReadITFlagPort() (R16_PA_INT_IF) + +/** + * @brief ȡGPIOB˿жϱ־״̬ + * + * @return GPIOB˿жϱ־״̬ + */ +#define GPIOB_ReadITFlagPort() ((R16_PB_INT_IF & (~((GPIO_Pin_22 | GPIO_Pin_23) >> 14))) | ((R16_PB_INT_IF << 14) & (GPIO_Pin_22 | GPIO_Pin_23))) + +/** + * @brief ȡGPIOA˿жϱ־״̬ + * + * @param pin - PA0-PA15 + * + * @return GPIOA˿жϱ־״̬ + */ +#define GPIOA_ReadITFlagBit(pin) (R16_PA_INT_IF & (pin)) + +/** + * @brief ȡGPIOB˿жϱ־״̬ + * + * @param pin - PB0-PB23 + * + * @return GPIOB˿жϱ־״̬ + */ +#define GPIOB_ReadITFlagBit(pin) (R16_PB_INT_IF & ((pin) | (((pin) & (GPIO_Pin_22 | GPIO_Pin_23)) >> 14))) + +/** + * @brief GPIOA˿жϱ־״̬ + * + * @param pin - PA0-PA15 + */ +#define GPIOA_ClearITFlagBit(pin) (R16_PA_INT_IF = pin) + +/** + * @brief GPIOB˿жϱ־״̬ + * + * @param pin - PB0-PB23 + */ +#define GPIOB_ClearITFlagBit(pin) (R16_PB_INT_IF = ((pin) | (((pin) & (GPIO_Pin_22 | GPIO_Pin_23)) >> 14))) + +/** + * @brief 蹦ӳ + * + * @param s - Ƿʹӳ + * @param perph - RB_RF_ANT_SW_EN - RF antenna switch control output on PB16/PB17/PB18/PB19/PB20/PB21 + * RB_PIN_U0_INV - RXD0/RXD0_/TXD0/TXD0_ invert input/output + * RB_PIN_INTX - INTX: INT24/INT25 PB8/PB9 -> INT24_/INT25_ PB22/PB23 + * RB_PIN_MODEM - MODEM: PB1/PB5 -> PB14/PB15 + * RB_PIN_I2C - I2C: PB13/PB12 -> PB21/PB20 + * RB_PIN_PWMX - PWMX: PA12/PA13/PB4/PB6/PB7 -> PA6/PA7/PB1/PB2/PB3 + * RB_PIN_SPI0 - SPI0: PA12/PA13/PA14/PA15 -> PB12/PB13/PB14/PB15 + * RB_PIN_UART3 - UART3: PA4/PA5 -> PB20/PB21 + * RB_PIN_UART2 - UART2: PA6/PA7 -> PB22/PB23 + * RB_PIN_UART1 - UART1: PA8/PA9 -> PB12/PB13 + * RB_PIN_UART0 - UART0: PB4/PB7 -> PA15/PA14 + * RB_PIN_TMR3 - TMR2: PA9 -> PB23 + * RB_PIN_TMR2 - TMR2: PA11 -> PB11 + * RB_PIN_TMR1 - TMR1: PA10 -> PB10 + * RB_PIN_TMR0 - TMR0: PA9 -> PB23 + */ +void GPIOPinRemap(FunctionalState s, uint16_t perph); + +/** + * @brief ģGPIOŹܿ + * + * @param s - Ƿģ蹦 + * @param perph - RB_PIN_ADC8_9_IE - ADC/TKEY 9/8ͨ + * RB_PIN_ADC6_7_IE - ADC/TKEY 7/6ͨ + * RB_PIN_ADC10_IE - ADC/TKEY 10ͨ + * RB_PIN_ADC11_IE - ADC/TKEY 11 ͨ + * RB_PIN_USB2_DP_PU - USB2 U2D+ڲ + * RB_PIN_USB2_IE - USB2 + * RB_PIN_USB_DP_PU - USB UD+ڲ + * RB_PIN_USB_IE - USB + * RB_PIN_ADC0_IE - ADC/TKEY 0 ͨ + * RB_PIN_ADC1_IE - ADC/TKEY 1 ͨ + * RB_PIN_ADC12_IE - ADC/TKEY 12 ͨ + * RB_PIN_ADC13_IE - ADC/TKEY 13 ͨ + * RB_PIN_XT32K_IE - 32KHzLSE + * RB_PIN_ADC2_3_IE - ADC/TKEY 2/3 ͨ + * RB_PIN_ADC4_5_IE - ADC/TKEY 4/5 ͨ + */ +void GPIOAGPPCfg(FunctionalState s, uint16_t perph); + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_GPIO_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_i2c.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_i2c.h new file mode 100644 index 0000000..1f30ced --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_i2c.h @@ -0,0 +1,180 @@ + + +#ifndef __CH58x_I2C_H__ +#define __CH58x_I2C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* I2C_transfer_direction */ +#define I2C_Direction_Transmitter ((uint8_t)0x00) +#define I2C_Direction_Receiver ((uint8_t)0x01) + +/* I2C ADD0 mask */ +#define OADDR1_ADD0_Set ((uint16_t)0x0001) +#define OADDR1_ADD0_Reset ((uint16_t)0xFFFE) + +/* I2C_NACK_position */ +#define I2C_NACKPosition_Next ((uint16_t)RB_I2C_POS) +#define I2C_NACKPosition_Current ((uint16_t)~RB_I2C_POS) + +/* I2C_PEC_position */ +#define I2C_PECPosition_Next ((uint16_t)RB_I2C_POS) +#define I2C_PECPosition_Current ((uint16_t)~RB_I2C_POS) + +/* I2C_SMBus_alert_pin_level */ +#define I2C_SMBusAlert_Low ((uint16_t)RB_I2C_ALERT) +#define I2C_SMBusAlert_High ((uint16_t)~RB_I2C_ALERT) + +/* I2C FLAG mask */ +#define FLAG_Mask ((uint32_t)0x00FFFFFF) + +/* I2C Interrupt Enable mask */ +#define ITEN_Mask ((uint32_t)0x07000000) + +/* I2C_mode */ +typedef enum +{ + I2C_Mode_I2C = 0x0000, + I2C_Mode_SMBusDevice = 0x0002, + I2C_Mode_SMBusHost = 0x000A, +} I2C_ModeTypeDef; + +/* I2C_duty_cycle_in_fast_mode */ +typedef enum +{ + I2C_DutyCycle_16_9 = RB_I2C_DUTY, /* I2C fast mode Tlow/Thigh = 16/9 */ + I2C_DutyCycle_2 = 0x0000, /* I2C fast mode Tlow/Thigh = 2 */ +} I2C_DutyTypeDef; + +/* I2C_acknowledgement - Enables or disables the acknowledgement.*/ +typedef enum +{ + I2C_Ack_Enable = RB_I2C_ACK, + I2C_Ack_Disable = 0x0000, +} I2C_AckTypeDef; + +/* I2C_acknowledged_address - Specifies if 7-bit or 10-bit address is acknowledged. */ +typedef enum +{ + I2C_AckAddr_7bit = 0x4000, + I2C_AckAddr_10bit = 0xC000, +} I2C_AckAddrTypeDef; + +/* I2C_interrupts_definition */ +typedef enum +{ + I2C_IT_BUF = 0x0400, /* Buffer interrupt mask. */ + I2C_IT_EVT = 0x0200, /* Event interrupt mask. */ + I2C_IT_ERR = 0x0100, /* Error interrupt mask. */ +} I2C_ITTypeDef; + +/* I2C_interrupts_definition */ +#define I2C_IT_SMBALERT ((uint32_t)0x01008000) +#define I2C_IT_TIMEOUT ((uint32_t)0x01004000) +#define I2C_IT_PECERR ((uint32_t)0x01001000) +#define I2C_IT_OVR ((uint32_t)0x01000800) +#define I2C_IT_AF ((uint32_t)0x01000400) +#define I2C_IT_ARLO ((uint32_t)0x01000200) +#define I2C_IT_BERR ((uint32_t)0x01000100) +#define I2C_IT_TXE ((uint32_t)0x06000080) +#define I2C_IT_RXNE ((uint32_t)0x06000040) +#define I2C_IT_STOPF ((uint32_t)0x02000010) +#define I2C_IT_ADD10 ((uint32_t)0x02000008) +#define I2C_IT_BTF ((uint32_t)0x02000004) +#define I2C_IT_ADDR ((uint32_t)0x02000002) +#define I2C_IT_SB ((uint32_t)0x02000001) + +/* SR2 register flags */ +#define I2C_FLAG_DUALF ((uint32_t)0x00800000) +#define I2C_FLAG_SMBHOST ((uint32_t)0x00400000) +#define I2C_FLAG_SMBDEFAULT ((uint32_t)0x00200000) +#define I2C_FLAG_GENCALL ((uint32_t)0x00100000) +#define I2C_FLAG_TRA ((uint32_t)0x00040000) +#define I2C_FLAG_BUSY ((uint32_t)0x00020000) +#define I2C_FLAG_MSL ((uint32_t)0x00010000) + +/* SR1 register flags */ +#define I2C_FLAG_SMBALERT ((uint32_t)0x10008000) +#define I2C_FLAG_TIMEOUT ((uint32_t)0x10004000) +#define I2C_FLAG_PECERR ((uint32_t)0x10001000) +#define I2C_FLAG_OVR ((uint32_t)0x10000800) +#define I2C_FLAG_AF ((uint32_t)0x10000400) +#define I2C_FLAG_ARLO ((uint32_t)0x10000200) +#define I2C_FLAG_BERR ((uint32_t)0x10000100) +#define I2C_FLAG_TXE ((uint32_t)0x10000080) +#define I2C_FLAG_RXNE ((uint32_t)0x10000040) +#define I2C_FLAG_STOPF ((uint32_t)0x10000010) +#define I2C_FLAG_ADD10 ((uint32_t)0x10000008) +#define I2C_FLAG_BTF ((uint32_t)0x10000004) +#define I2C_FLAG_ADDR ((uint32_t)0x10000002) +#define I2C_FLAG_SB ((uint32_t)0x10000001) + +/****************I2C Master Events (Events grouped in order of communication)********************/ + +#define I2C_EVENT_MASTER_MODE_SELECT ((uint32_t)0x00030001) /* BUSY, MSL and SB flag */ +#define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070082) /* BUSY, MSL, ADDR, TXE and TRA flags */ +#define I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ((uint32_t)0x00030002) /* BUSY, MSL and ADDR flags */ +#define I2C_EVENT_MASTER_MODE_ADDRESS10 ((uint32_t)0x00030008) /* BUSY, MSL and ADD10 flags */ +#define I2C_EVENT_MASTER_BYTE_RECEIVED ((uint32_t)0x00030040) /* BUSY, MSL and RXNE flags */ +#define I2C_EVENT_MASTER_BYTE_TRANSMITTING ((uint32_t)0x00070080) /* TRA, BUSY, MSL, TXE flags */ +#define I2C_EVENT_MASTER_BYTE_TRANSMITTED ((uint32_t)0x00070084) /* TRA, BUSY, MSL, TXE and BTF flags */ + +/******************I2C Slave Events (Events grouped in order of communication)******************/ + +#define I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED ((uint32_t)0x00020002) /* BUSY and ADDR flags */ +#define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */ +#define I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED ((uint32_t)0x00820000) /* DUALF and BUSY flags */ +#define I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED ((uint32_t)0x00860080) /* DUALF, TRA, BUSY and TXE flags */ +#define I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED ((uint32_t)0x00120000) /* GENCALL and BUSY flags */ +#define I2C_EVENT_SLAVE_BYTE_RECEIVED ((uint32_t)0x00020040) /* BUSY and RXNE flags */ +#define I2C_EVENT_SLAVE_STOP_DETECTED ((uint32_t)0x00000010) /* STOPF flag */ +#define I2C_EVENT_SLAVE_BYTE_TRANSMITTED ((uint32_t)0x00060084) /* TRA, BUSY, TXE and BTF flags */ +#define I2C_EVENT_SLAVE_BYTE_TRANSMITTING ((uint32_t)0x00060080) /* TRA, BUSY and TXE flags */ +#define I2C_EVENT_SLAVE_ACK_FAILURE ((uint32_t)0x00000400) /* AF flag */ + +void I2C_Init(I2C_ModeTypeDef I2C_Mode, UINT32 I2C_ClockSpeed, I2C_DutyTypeDef I2C_DutyCycle, + I2C_AckTypeDef I2C_Ack, I2C_AckAddrTypeDef I2C_AckAddr, UINT16 I2C_OwnAddress1); +void I2C_Cmd(FunctionalState NewState); +void I2C_GenerateSTART(FunctionalState NewState); +void I2C_GenerateSTOP(FunctionalState NewState); +void I2C_AcknowledgeConfig(FunctionalState NewState); +void I2C_OwnAddress2Config(uint8_t Address); +void I2C_DualAddressCmd(FunctionalState NewState); +void I2C_GeneralCallCmd(FunctionalState NewState); +void I2C_ITConfig(I2C_ITTypeDef I2C_IT, FunctionalState NewState); +void I2C_SendData(uint8_t Data); + +uint8_t I2C_ReceiveData(void); + +void I2C_Send7bitAddress(uint8_t Address, uint8_t I2C_Direction); +void I2C_SoftwareResetCmd(FunctionalState NewState); +void I2C_NACKPositionConfig(uint16_t I2C_NACKPosition); +void I2C_SMBusAlertConfig(uint16_t I2C_SMBusAlert); +void I2C_TransmitPEC(FunctionalState NewState); +void I2C_PECPositionConfig(uint16_t I2C_PECPosition); +void I2C_CalculatePEC(FunctionalState NewState); + +uint8_t I2C_GetPEC(void); + +void I2C_ARPCmd(FunctionalState NewState); +void I2C_StretchClockCmd(FunctionalState NewState); +void I2C_FastModeDutyCycleConfig(uint16_t I2C_DutyCycle); + +/**************************************************************************************** + * I2C State Monitoring Functions + ****************************************************************************************/ +uint8_t I2C_CheckEvent(uint32_t I2C_EVENT); +uint32_t I2C_GetLastEvent(void); +FlagStatus I2C_GetFlagStatus(uint32_t I2C_FLAG); + +void I2C_ClearFlag(uint32_t I2C_FLAG); +ITStatus I2C_GetITStatus(uint32_t I2C_IT); +void I2C_ClearITPendingBit(uint32_t I2C_IT); + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_I2C_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_pwm.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_pwm.h new file mode 100644 index 0000000..75b018a --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_pwm.h @@ -0,0 +1,152 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_pwm.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_PWM_H__ +#define __CH58x_PWM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief channel of PWM define + */ +#define CH_PWM4 0x01 // PWM4 ͨ +#define CH_PWM5 0x02 // PWM5 ͨ +#define CH_PWM6 0x04 // PWM6 ͨ +#define CH_PWM7 0x08 // PWM7 ͨ +#define CH_PWM8 0x10 // PWM8 ͨ +#define CH_PWM9 0x20 // PWM9 ͨ +#define CH_PWM10 0x40 // PWM10 ͨ +#define CH_PWM11 0x80 // PWM11 ͨ + +/** + * @brief channel of PWM define + */ +typedef enum +{ + High_Level = 0, // Ĭϵ͵ƽߵƽЧ + Low_Level, // Ĭϸߵƽ͵ƽЧ +} PWMX_PolarTypeDef; + +/** + * @brief Configuration PWM4_11 Cycle size + */ +typedef enum +{ + PWMX_Cycle_256 = 0, // 256 PWMX + PWMX_Cycle_255, // 255 PWMX + PWMX_Cycle_128, // 128 PWMX + PWMX_Cycle_127, // 127 PWMX + PWMX_Cycle_64, // 64 PWMX + PWMX_Cycle_63, // 63 PWMX + PWMX_Cycle_32, // 32 PWMX + PWMX_Cycle_31, // 31 PWMX +} PWMX_CycleTypeDef; + +/** + * @brief PWM4-PWM11 ͨ׼ʱ + * + * @param d - ͨ׼ʱ = d*Tsys + */ +#define PWMX_CLKCfg(d) (R8_PWM_CLOCK_DIV = d) + +/** + * @brief PWM4-PWM11׼ʱ + * + * @param cyc - refer to PWMX_CycleTypeDef + */ +void PWMX_CycleCfg(PWMX_CycleTypeDef cyc); + +/** + * @brief PWM4 Ч + * + * @param d - Ч + */ +#define PWM4_ActDataWidth(d) (R8_PWM4_DATA = d) + +/** + * @brief PWM5 Ч + * + * @param d - Ч + */ +#define PWM5_ActDataWidth(d) (R8_PWM5_DATA = d) + +/** + * @brief PWM6 Ч + * + * @param d - Ч + */ +#define PWM6_ActDataWidth(d) (R8_PWM6_DATA = d) + +/** + * @brief PWM7 Ч + * + * @param d - Ч + */ +#define PWM7_ActDataWidth(d) (R8_PWM7_DATA = d) + +/** + * @brief PWM8 Ч + * + * @param d - Ч + */ +#define PWM8_ActDataWidth(d) (R8_PWM8_DATA = d) + +/** + * @brief PWM9 Ч + * + * @param d - Ч + */ +#define PWM9_ActDataWidth(d) (R8_PWM9_DATA = d) + +/** + * @brief PWM10 Ч + * + * @param d - Ч + */ +#define PWM10_ActDataWidth(d) (R8_PWM10_DATA = d) + +/** + * @brief PWM11 Ч + * + * @param d - Ч + */ +#define PWM11_ActDataWidth(d) (R8_PWM11_DATA = d) + +/** + * @brief PWM4-PWM11ͨ + * + * @param ch - select channel of pwm, refer to channel of PWM define + * @param da - effective pulse width + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param s - control pwmx function, ENABLE or DISABLE + */ +void PWMX_ACTOUT(uint8_t ch, uint8_t da, PWMX_PolarTypeDef pr, FunctionalState s); + +/** + * @brief PWM ģʽ + * + * @param ch - select group of PWM alternate output + * RB_PWM4_5_STAG_EN - PWM4 PWM5 ͨ + * RB_PWM6_7_STAG_EN - PWM6 PWM7 ͨ + * RB_PWM8_9_STAG_EN - PWM8 PWM9 ͨ + * RB_PWM10_11_STAG_EN - PWM10 PWM11 ͨ + * @param s - control pwmx function, ENABLE or DISABLE + */ +void PWMX_AlterOutCfg(uint8_t ch, FunctionalState s); + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_PWM_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_pwr.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_pwr.h new file mode 100644 index 0000000..abf4d08 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_pwr.h @@ -0,0 +1,167 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_pwr.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_PWR_H__ +#define __CH58x_PWR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Peripher CLK control bit define + */ +#define BIT_SLP_CLK_TMR0 (0x00000001) /*!< TMR0 peripher clk bit */ +#define BIT_SLP_CLK_TMR1 (0x00000002) /*!< TMR1 peripher clk bit */ +#define BIT_SLP_CLK_TMR2 (0x00000004) /*!< TMR2 peripher clk bit */ +#define BIT_SLP_CLK_TMR3 (0x00000008) /*!< TMR3 peripher clk bit */ +#define BIT_SLP_CLK_UART0 (0x00000010) /*!< UART0 peripher clk bit */ +#define BIT_SLP_CLK_UART1 (0x00000020) /*!< UART1 peripher clk bit */ +#define BIT_SLP_CLK_UART2 (0x00000040) /*!< UART2 peripher clk bit */ +#define BIT_SLP_CLK_UART3 (0x00000080) /*!< UART3 peripher clk bit */ +#define BIT_SLP_CLK_SPI0 (0x00000100) /*!< SPI0 peripher clk bit */ +//#define BIT_SLP_CLK_SPI1 (0x00000200) /*!< SPI1 peripher clk bit */ +#define BIT_SLP_CLK_PWMX (0x00000400) /*!< PWMX peripher clk bit */ +//#define BIT_SLP_CLK_LCD (0x00000800) /*!< LCD peripher clk bit */ +#define BIT_SLP_CLK_USB (0x00001000) /*!< USB peripher clk bit */ +//#define BIT_SLP_CLK_ETH (0x00002000) /*!< ETH peripher clk bit */ +//#define BIT_SLP_CLK_LED (0x00004000) /*!< LED peripher clk bit */ +#define BIT_SLP_CLK_BLE (0x00008000) /*!< BLE peripher clk bit */ + +#define BIT_SLP_CLK_RAMX (0x10000000) /*!< main SRAM RAM16K peripher clk bit */ +#define BIT_SLP_CLK_RAM2K (0x20000000) /*!< RAM2K peripher clk bit */ +#define BIT_SLP_CLK_ALL (0x3000FFFF) /*!< All peripher clk bit */ + +/** + * @brief unit of controllable power supply + */ +#define UNIT_SYS_LSE RB_CLK_XT32K_PON // ⲿ32K ʱ +#define UNIT_SYS_LSI RB_CLK_INT32K_PON // ڲ32K ʱ +#define UNIT_SYS_HSE RB_CLK_XT32M_PON // ⲿ32M ʱ +#define UNIT_SYS_PLL RB_CLK_PLL_PON // PLL ʱ + +/** + * @brief wakeup mode define + */ +typedef enum +{ + Short_Delay = 0, + Long_Delay, + +} WakeUP_ModeypeDef; + +/** + * @brief wakeup mode define + */ +typedef enum +{ + /* ȼʹø߾ȼأ210uA */ + HALevel_1V9 = 0, // 1.7-1.9 + HALevel_2V1, // 1.9-2.1 + HALevel_2V3, // 2.1-2.3 + HALevel_2V5, // 2.3-2.5 + + /* ȼʹõ͹ļأ1uA */ + LPLevel_1V8 = 0x80, + LPLevel_1V9, + LPLevel_2V0, + LPLevel_2V1, + LPLevel_2V2, + LPLevel_2V3, + LPLevel_2V4, + LPLevel_2V5, + +} VolM_LevelypeDef; + +/** + * @brief ڲDC/DCԴڽԼϵͳ + * + * @param s - ǷDCDCԴ + */ +void PWR_DCDCCfg(FunctionalState s); + +/** + * @brief ɿصԪģĵԴ + * + * @param s - Ƿ򿪵Դ + * @param unit - please refer to unit of controllable power supply + */ +void PWR_UnitModCfg(FunctionalState s, uint8_t unit); + +/** + * @brief ʱӿλ + * + * @param s - Ƿ򿪶Ӧʱ + * @param perph - please refer to Peripher CLK control bit define + */ +void PWR_PeriphClkCfg(FunctionalState s, uint16_t perph); + +/** + * @brief ˯߻Դ + * + * @param s - Ƿ򿪴˯߻ѹ + * @param perph - ҪõĻԴ + * RB_SLP_USB_WAKE - USB ΪԴ + * RB_SLP_RTC_WAKE - RTC ΪԴ + * RB_SLP_GPIO_WAKE - GPIO ΪԴ + * RB_SLP_BAT_WAKE - BAT ΪԴ + * @param mode - refer to WakeUP_ModeypeDef + */ +void PWR_PeriphWakeUpCfg(FunctionalState s, uint8_t perph, WakeUP_ModeypeDef mode); + +/** + * @brief Դ + * + * @param s - Ƿ򿪴˹ + * @param vl - refer to VolM_LevelypeDef + */ +void PowerMonitor(FunctionalState s, VolM_LevelypeDef vl); + +/** + * @brief ͹-Idleģʽ + */ +void LowPower_Idle(void); + +/** + * @brief ͹-Haltģʽ˵͹еHSI/5ʱУѺҪûԼѡϵͳʱԴ + */ +void LowPower_Halt(void); + +/** + * @brief ͹-Sleepģʽ˵͹еHSI/5ʱУѺҪûԼѡϵͳʱԴ + * @note עô˺DCDCǿƹرգѺֶٴδ + * + * @param rm - ģѡ + * RB_PWR_RAM2K - 2K retention SRAM + * RB_PWR_RAM16K - 16K main SRAM + * RB_PWR_EXTEND - USB BLE Ԫ򹩵 + * RB_PWR_XROM - FlashROM + * NULL - ϵԪϵ + */ +void LowPower_Sleep(uint8_t rm); + +/** + * @brief ͹-Shutdownģʽ˵͹еHSI/5ʱУѺҪûԼѡϵͳʱԴ + * @note עô˺DCDCǿƹرգѺֶٴδ + * + * @param rm - ģѡ + * RB_PWR_RAM2K - 2K retention SRAM + * RB_PWR_RAM16K - 16K main SRAM + * NULL - ϵԪϵ + */ +void LowPower_Shutdown(uint8_t rm); + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_PWR_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_spi.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_spi.h new file mode 100644 index 0000000..6d7b176 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_spi.h @@ -0,0 +1,209 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_SPI.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_SPI_H__ +#define __CH58x_SPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief SPI0 interrupt bit define + */ +#define SPI0_IT_FST_BYTE RB_SPI_IE_FST_BYTE // ӻģʽֽģʽ£յֽж +#define SPI0_IT_FIFO_OV RB_SPI_IE_FIFO_OV // FIFO +#define SPI0_IT_DMA_END RB_SPI_IE_DMA_END // DMA +#define SPI0_IT_FIFO_HF RB_SPI_IE_FIFO_HF // FIFO ʹù +#define SPI0_IT_BYTE_END RB_SPI_IE_BYTE_END // ֽڴ +#define SPI0_IT_CNT_END RB_SPI_IE_CNT_END // ȫֽڴ + +/** + * @brief Configuration data mode + */ +typedef enum +{ + Mode0_LowBitINFront = 0, // ģʽ0λǰ + Mode0_HighBitINFront, // ģʽ0λǰ + Mode3_LowBitINFront, // ģʽ3λǰ + Mode3_HighBitINFront, // ģʽ3λǰ +} ModeBitOrderTypeDef; + +/** + * @brief Configuration SPI0 slave mode + */ +typedef enum +{ + Mode_DataStream = 0, // ģʽ + Mose_FirstCmd, // ֽģʽ +} Slave_ModeTypeDef; + +/** + * @brief ģʽĬϳʼģʽ0+3ȫ˫+8MHz + */ +void SPI0_MasterDefInit(void); + +/** + * @brief SPI0 ׼ʱã= d*Tsys + * + * @param c - ʱӷƵϵ + */ +void SPI0_CLKCfg(uint8_t c); + +/** + * @brief ģʽ + * + * @param m - ģʽ refer to ModeBitOrderTypeDef + */ +void SPI0_DataMode(ModeBitOrderTypeDef m); + +/** + * @brief ͵ֽ (buffer) + * + * @param d - ֽ + */ +void SPI0_MasterSendByte(uint8_t d); + +/** + * @brief յֽ (buffer) + * + * @param none + */ +uint8_t SPI0_MasterRecvByte(void); + +/** + * @brief ʹFIFOͶֽ + * + * @param pbuf - ͵׵ַ + * @param len - ͵ݳȣ4095 + */ +void SPI0_MasterTrans(uint8_t *pbuf, uint16_t len); + +/** + * @brief ʹFIFOնֽ + * + * @param pbuf - յ׵ַ + * @param len - յݳȣ4095 + */ +void SPI0_MasterRecv(uint8_t *pbuf, uint16_t len); + +/** + * @brief DMAʽ + * + * @param pbuf - ʼַ,Ҫֽڶ + * @param len - ݳ + */ +void SPI0_MasterDMATrans(uint8_t *pbuf, uint16_t len); + +/** + * @brief DMAʽ + * + * @param pbuf - ݴʼַ,Ҫֽڶ + * @param len - ݳ + */ +void SPI0_MasterDMARecv(uint8_t *pbuf, uint16_t len); + +void SPI1_MasterDefInit(void); /* ģʽĬϳʼģʽ0+3ȫ˫+8MHz */ +void SPI1_CLKCfg(UINT8 c); /* SPI1 ׼ʱã= d*Tsys */ +void SPI1_DataMode(ModeBitOrderTypeDef m); /* ģʽ */ + +void SPI1_MasterSendByte(UINT8 d); /* ͵ֽ (buffer) */ +UINT8 SPI1_MasterRecvByte(void); /* յֽ (buffer) */ + +void SPI1_MasterTrans(UINT8 *pbuf, UINT16 len); /* ʹFIFOͶֽ */ +void SPI1_MasterRecv(UINT8 *pbuf, UINT16 len); /* ʹFIFOնֽ */ + +/** + * @brief 豸ģʽĬϳʼMISOGPIOӦΪģʽ + */ +void SPI0_SlaveInit(void); + +/** + * @brief ֽ + * + * @param d - ֽ + */ +#define SetFirstData(d) (R8_SPI0_SLAVE_PRE = d) + +/** + * @brief ӻģʽһֽ + * + * @param d - + */ +void SPI0_SlaveSendByte(uint8_t d); + +/** + * @brief ӻģʽһֽ + * + * @return յ + */ +uint8_t SPI0_SlaveRecvByte(void); + +/** + * @brief ӻģʽͶֽ + * + * @param pbuf - ͵׵ַ + * @param len - ͵ݳȣ4095 + */ +void SPI0_SlaveTrans(uint8_t *pbuf, uint16_t len); + +/** + * @brief ӻģʽնֽ + * + * @param pbuf - ݴʼַ + * @param len - ݳ + */ +void SPI0_SlaveRecv(uint8_t *pbuf, uint16_t len); + +/** + * @brief DMAʽ + * + * @param pbuf - ʼַ,Ҫֽڶ + * @param len - ݳ + */ +void SPI0_SlaveDMATrans(uint8_t *pbuf, uint16_t len); + +/** + * @brief DMAʽ + * + * @param pbuf - ݴʼַ,Ҫֽڶ + * @param len - ݳ + */ +void SPI0_SlaveDMARecv(uint8_t *pbuf, uint16_t len); + +/** + * @brief SPI0ж + * + * @param s - ʹ/ر + * @param f - refer to SPI0 interrupt bit define + */ +#define SPI0_ITCfg(s, f) ((s) ? (R8_SPI0_INTER_EN |= f) : (R8_SPI0_INTER_EN &= ~f)) + +/** + * @brief ȡжϱ־״̬0-δλ(!0)- + * + * @param f - refer to SPI0 interrupt bit define + */ +#define SPI0_GetITFlag(f) (R8_SPI0_INT_FLAG & f) + +/** + * @brief ǰжϱ־ + * + * @param f - refer to SPI0 interrupt bit define + */ +#define SPI0_ClearITFlag(f) (R8_SPI0_INT_FLAG = f) + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_SPI_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_sys.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_sys.h new file mode 100644 index 0000000..b98a7f7 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_sys.h @@ -0,0 +1,194 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_SYS.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_SYS_H__ +#define __CH58x_SYS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief rtc interrupt event define + */ +typedef enum +{ + RST_STATUS_SW = 0, // λ + RST_STATUS_RPOR, // ϵ縴λ + RST_STATUS_WTR, // Źʱλ + RST_STATUS_MR, // ⲿֶλ + RST_STATUS_LRM0, // Ѹλ-λ + RST_STATUS_GPWSM, // µģʽѸλ + RST_STATUS_LRM1, // Ѹλ-Ź + RST_STATUS_LRM2, // Ѹλ-ֶλ + +} SYS_ResetStaTypeDef; + +/** + * @brief rtc interrupt event define + */ +typedef enum +{ + INFO_ROM_READ = 0, // FlashROM Ƿɶ + INFO_RESET_EN = 2, // RST#ⲿֶλ빦Ƿ + INFO_BOOT_EN, // ϵͳ BootLoader Ƿ + INFO_DEBUG_EN, // ϵͳԽӿǷ + INFO_LOADER, // ǰϵͳǷBootloader + STA_SAFEACC_ACT, // ǰϵͳǷڰȫ״̬RWA򲻿ɷ + +} SYS_InfoStaTypeDef; + +/** + * @brief ȡоƬID࣬һΪ̶ֵ + */ +#define SYS_GetChipID() R8_CHIP_ID + +/** + * @brief ȡȫIDһΪ̶ֵ + */ +#define SYS_GetAccessID() R8_SAFE_ACCESS_ID + +/** + * @brief ϵͳʱ + * + * @param sc - ϵͳʱԴѡ refer to SYS_CLKTypeDef + */ +void SetSysClock(SYS_CLKTypeDef sc); + +/** + * @brief ȡǰϵͳʱ + * + * @return Hz + */ +uint32_t GetSysClock(void); + +/** + * @brief ȡǰϵͳϢ״̬ + * + * @param i - refer to SYS_InfoStaTypeDef + * + * @return Ƿ + */ +uint8_t SYS_GetInfoSta(SYS_InfoStaTypeDef i); + +/** + * @brief ȡϵͳϴθλ״̬ + * + * @return refer to SYS_ResetStaTypeDef + */ +#define SYS_GetLastResetSta() (R8_RESET_STATUS & RB_RESET_FLAG) + +/** + * @brief ִϵͳλ + */ +void SYS_ResetExecute(void); + +/** + * @brief øλĴֵֶλ λ ŹλͨѸλӰ + * + * @param i - refer to SYS_InfoStaTypeDef + */ +#define SYS_ResetKeepBuf(d) (R8_GLOB_RESET_KEEP = d) + +/** + * @brief رжϣǰжֵ + * + * @param pirqv - ǰжֵ + */ +void SYS_DisableAllIrq(uint32_t *pirqv); + +/** + * @brief ָ֮ǰرյжֵ + * + * @param irq_status - ǰжֵ + */ +void SYS_RecoverIrq(uint32_t irq_status); + +/** + * @brief ȡǰϵͳ(SYSTICK)ֵ + * + * @return ǰֵ + */ +uint32_t SYS_GetSysTickCnt(void); + +/** + * @brief ؿŹֵ + * + * @param c - Źֵ + */ +#define WWDG_SetCounter(c) (R8_WDOG_COUNT = c) + +/** + * @brief Źʱжʹ + * + * @param s - Ƿж + */ +void WWDG_ITCfg(FunctionalState s); + +/** + * @brief Źʱλ + * + * @param s - Ƿλ + */ +void WWDG_ResetCfg(FunctionalState s); + +/** + * @brief ȡǰŹʱ־ + * + * @return Źʱ־ + */ +#define WWDG_GetFlowFlag() (R8_RST_WDOG_CTRL & RB_WDOG_INT_FLAG) + +/** + * @brief Źжϱ־¼ؼֵҲ + */ +void WWDG_ClearFlag(void); + +/** + * @brief uS ʱ + * + * @param t - ʱ + */ +void mDelayuS(uint16_t t); + +/** + * @brief mS ʱ + * + * @param t - ʱ + */ +void mDelaymS(uint16_t t); + +/** + * @brief Enter safe access mode. + * + * @NOTE: After enter safe access mode, about 16 system frequency cycles + * are in safe mode, and one or more secure registers can be rewritten + * within the valid period. The safe mode will be automatically + * terminated after the above validity period is exceeded. + */ + __attribute__((always_inline)) static inline void sys_safe_access_enable(void) +{ + R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; + R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; + SAFEOPERATE; +} + +__attribute__((always_inline)) static inline void sys_safe_access_disable(void) +{ + R8_SAFE_ACCESS_SIG = 0; +} + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_SYS_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_timer.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_timer.h new file mode 100644 index 0000000..0da5fa3 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_timer.h @@ -0,0 +1,555 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_timer.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_TIMER_H__ +#define __CH58x_TIMER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define DataBit_25 (1 << 25) + +/** + * @brief TMR0 interrupt bit define + */ + +#define TMR0_3_IT_CYC_END 0x01 // ڽ־׽-ʱʱ-ڽPWM-ڽ +#define TMR0_3_IT_DATA_ACT 0x02 // Ч־׽-ݣPWM-Чƽ +#define TMR0_3_IT_FIFO_HF 0x04 // FIFO ʹù룺׽- FIFO>=4 PWM- FIFO<4 +#define TMR1_2_IT_DMA_END 0x08 // DMA ֧TMR1TMR2 +#define TMR0_3_IT_FIFO_OV 0x10 // FIFO ׽- FIFO PWM- FIFO + +/** + * @brief Configuration PWM effective level repeat times + */ +typedef enum +{ + PWM_Times_1 = 0, // PWM Чظ1 + PWM_Times_4, // PWM Чظ4 + PWM_Times_8, // PWM Чظ8 + PWM_Times_16, // PWM Чظ16 +} PWM_RepeatTsTypeDef; + +/** + * @brief Configuration Cap mode + */ +typedef enum +{ + CAP_NULL = 0, // ׽ & + Edge_To_Edge, // ֮ & + FallEdge_To_FallEdge, // ½ص½ & ½ + RiseEdge_To_RiseEdge, // ص & +} CapModeTypeDef; + +/** + * @brief Configuration DMA mode + */ +typedef enum +{ + Mode_Single = 0, // ģʽ + Mode_LOOP, // ѭģʽ +} DMAModeTypeDef; + +/** + * @brief ʱܳʼ + * + * @param t - ʱʱ䣬ڵǰϵͳʱTsys, ʱ 67108864 + */ +void TMR0_TimerInit(uint32_t t); + +/** + * @brief ȡǰʱֵ67108864 + * + * @return ǰʱֵ + */ +#define TMR0_GetCurrentTimer() R32_TMR0_COUNT + +/** + * @brief ؼܳʼ + * + * @param cap - ɼ + */ +void TMR0_EXTSingleCounterInit(CapModeTypeDef cap); + +/** + * @brief üͳС67108862 + * + * @param cyc - ͳС + */ +#define TMR0_CountOverflowCfg(cyc) (R32_TMR0_CNT_END = (cyc + 2)) + +/** + * @brief ȡǰֵ67108862 + * + * @return ǰֵ + */ +#define TMR0_GetCurrentCount() R32_TMR0_COUNT + +/** + * @brief PWM0 ͨ, 67108864 + * + * @param cyc - + */ +#define TMR0_PWMCycleCfg(cyc) (R32_TMR0_CNT_END = cyc) + +/** + * @brief PWM ʼ + * + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param ts - set pwm repeat times, refer to PWM_RepeatTsTypeDef + */ +void TMR0_PWMInit(PWMX_PolarTypeDef pr, PWM_RepeatTsTypeDef ts); + +/** + * @brief PWM0 Ч, 67108864 + * + * @param d - Ч + */ +#define TMR0_PWMActDataWidth(d) (R32_TMR0_FIFO = d) + +/** + * @brief CAP0 ׽ƽʱ, 33554432 + * + * @param cyc - ׽ƽʱ + */ +#define TMR0_CAPTimeoutCfg(cyc) (R32_TMR0_CNT_END = cyc) + +/** + * @brief ⲿźŲ׽ܳʼ + * + * @param cap - select capture mode, refer to CapModeTypeDef + */ +void TMR0_CapInit(CapModeTypeDef cap); + +/** + * @brief ȡ + * + * @return + */ +#define TMR0_CAPGetData() R32_TMR0_FIFO + +/** + * @brief ȡǰѲݸ + * + * @return ǰѲݸ + */ +#define TMR0_CAPDataCounter() R8_TMR0_FIFO_COUNT + +/** + * @brief ر TMR0 + */ +#define TMR0_Disable() (R8_TMR0_CTRL_MOD &= ~RB_TMR_COUNT_EN) + +/** + * @brief TMR0 + */ +#define TMR0_Enable() (R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN) + +/** + * @brief ж + * + * @param s - ʹ/ر + * @param f - refer to TMR interrupt bit define + */ +#define TMR0_ITCfg(s, f) ((s) ? (R8_TMR0_INTER_EN |= f) : (R8_TMR0_INTER_EN &= ~f)) + +/** + * @brief жϱ־ + * + * @param f - refer to TMR interrupt bit define + */ +#define TMR0_ClearITFlag(f) (R8_TMR0_INT_FLAG = f) + +/** + * @brief ѯжϱ־״̬ + * + * @param f - refer to TMR interrupt bit define + */ +#define TMR0_GetITFlag(f) (R8_TMR0_INT_FLAG & f) + +/** + * @brief ʱܳʼ + * + * @param t - ʱʱ䣬ڵǰϵͳʱTsys, ʱ 67108864 + */ +void TMR1_TimerInit(uint32_t t); + +/** + * @brief ȡǰʱֵ67108864 + * + * @return ǰʱֵ + */ +#define TMR1_GetCurrentTimer() R32_TMR1_COUNT + +/** + * @brief ؼܳʼ + * + * @param cap - ɼ + */ +void TMR1_EXTSingleCounterInit(CapModeTypeDef cap); + +/** + * @brief üͳС67108862 + * + * @param cyc - ͳС + */ +#define TMR1_CountOverflowCfg(cyc) (R32_TMR1_CNT_END = (cyc + 2)) + +/** + * @brief ȡǰֵ67108862 + * + * @return ǰֵ + */ +#define TMR1_GetCurrentCount() R32_TMR1_COUNT + +/** + * @brief PWM1 ͨ, 67108864 + * + * @param cyc - + */ +#define TMR1_PWMCycleCfg(cyc) (R32_TMR1_CNT_END = cyc) + +/** + * @brief PWM ʼ + * + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param ts - set pwm repeat times, refer to PWM_RepeatTsTypeDef + */ +void TMR1_PWMInit(PWMX_PolarTypeDef pr, PWM_RepeatTsTypeDef ts); + +/** + * @brief PWM1 Ч, 67108864 + * + * @param d - Ч + */ +#define TMR1_PWMActDataWidth(d) (R32_TMR1_FIFO = d) + +/** + * @brief CAP1 ׽ƽʱ, 33554432 + * + * @param cyc - ׽ƽʱ + */ +#define TMR1_CAPTimeoutCfg(cyc) (R32_TMR1_CNT_END = cyc) + +/** + * @brief ⲿźŲ׽ܳʼ + * + * @param cap - select capture mode, refer to CapModeTypeDef + */ +void TMR1_CapInit(CapModeTypeDef cap); + +/** + * @brief ȡ + * + * @return + */ +#define TMR1_CAPGetData() R32_TMR1_FIFO + +/** + * @brief ȡǰѲݸ + * + * @return ǰѲݸ + */ +#define TMR1_CAPDataCounter() R8_TMR1_FIFO_COUNT + +/** + * @brief DMA + * + * @param s - ǷDMA + * @param startAddr - DMA ʼַ + * @param endAddr - DMA ַ + * @param m - DMAģʽ + */ +void TMR1_DMACfg(uint8_t s, uint16_t startAddr, uint16_t endAddr, DMAModeTypeDef m); + +/** + * @brief ر TMR1 + */ +#define TMR1_Disable() (R8_TMR1_CTRL_MOD &= ~RB_TMR_COUNT_EN) + +/** + * @brief TMR1 + */ +#define TMR1_Enable() (R8_TMR1_CTRL_MOD |= RB_TMR_COUNT_EN) + +/** + * @brief ж + * + * @param s - ʹ/ر + * @param f - refer to TMR interrupt bit define + */ +#define TMR1_ITCfg(s, f) ((s) ? (R8_TMR1_INTER_EN |= f) : (R8_TMR1_INTER_EN &= ~f)) + +/** + * @brief жϱ־ + * + * @param f - refer to TMR interrupt bit define + */ +#define TMR1_ClearITFlag(f) (R8_TMR1_INT_FLAG = f) + +/** + * @brief ѯжϱ־״̬ + * + * @param f - refer to TMR interrupt bit define + */ +#define TMR1_GetITFlag(f) (R8_TMR1_INT_FLAG & f) + +/** + * @brief ʱܳʼ + * + * @param t - ʱʱ䣬ڵǰϵͳʱTsys, ʱ 67108864 + */ +void TMR2_TimerInit(uint32_t t); + +/** + * @brief ȡǰʱֵ67108864 + * + * @return ǰʱֵ + */ +#define TMR2_GetCurrentTimer() R32_TMR2_COUNT + +/** + * @brief ؼܳʼ + * + * @param cap - ɼ + */ +void TMR2_EXTSingleCounterInit(CapModeTypeDef cap); + +/** + * @brief üͳС67108862 + * + * @param cyc - ͳС + */ +#define TMR2_CountOverflowCfg(cyc) (R32_TMR2_CNT_END = (cyc + 2)) + +/** + * @brief ȡǰֵ67108862 + * + * @return ǰֵ + */ +#define TMR2_GetCurrentCount() R32_TMR2_COUNT + +/** + * @brief PWM2 ͨ, 67108864 + * + * @param cyc - + */ +#define TMR2_PWMCycleCfg(cyc) (R32_TMR2_CNT_END = cyc) + +/** + * @brief PWM ʼ + * + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param ts - set pwm repeat times, refer to PWM_RepeatTsTypeDef + */ +void TMR2_PWMInit(PWMX_PolarTypeDef pr, PWM_RepeatTsTypeDef ts); + +/** + * @brief PWM2 Ч, 67108864 + * + * @param d - Ч + */ +#define TMR2_PWMActDataWidth(d) (R32_TMR2_FIFO = d) + +/** + * @brief CAP2 ׽ƽʱ, 33554432 + * + * @param cyc - ׽ƽʱ + */ +#define TMR2_CAPTimeoutCfg(cyc) (R32_TMR2_CNT_END = cyc) + +/** + * @brief ⲿźŲ׽ܳʼ + * + * @param cap - select capture mode, refer to CapModeTypeDef + */ +void TMR2_CapInit(CapModeTypeDef cap); + +/** + * @brief ȡ + * + * @return + */ +#define TMR2_CAPGetData() R32_TMR2_FIFO + +/** + * @brief ȡǰѲݸ + * + * @return ǰѲݸ + */ +#define TMR2_CAPDataCounter() R8_TMR2_FIFO_COUNT + +/** + * @brief DMA + * + * @param s - ǷDMA + * @param startAddr - DMA ʼַ + * @param endAddr - DMA ַ + * @param m - DMAģʽ + */ +void TMR2_DMACfg(uint8_t s, uint16_t startAddr, uint16_t endAddr, DMAModeTypeDef m); + +/** + * @brief ر TMR2 + */ +#define TMR2_Disable() (R8_TMR2_CTRL_MOD &= ~RB_TMR_COUNT_EN) + +/** + * @brief TMR2 + */ +#define TMR2_Enable() (R8_TMR2_CTRL_MOD |= RB_TMR_COUNT_EN) + +/** + * @brief ж + * + * @param s - ʹ/ر + * @param f - refer to TMR interrupt bit define + */ +#define TMR2_ITCfg(s, f) ((s) ? (R8_TMR2_INTER_EN |= f) : (R8_TMR2_INTER_EN &= ~f)) + +/** + * @brief жϱ־ + * + * @param f - refer to TMR interrupt bit define + */ +#define TMR2_ClearITFlag(f) (R8_TMR2_INT_FLAG = f) + +/** + * @brief ѯжϱ־״̬ + * + * @param f - refer to TMR interrupt bit define + */ +#define TMR2_GetITFlag(f) (R8_TMR2_INT_FLAG & f) + +/** + * @brief ʱܳʼ + * + * @param t - ʱʱ䣬ڵǰϵͳʱTsys, ʱ 67108864 + */ +void TMR3_TimerInit(uint32_t t); + +/** + * @brief ȡǰʱֵ67108864 + * + * @return ǰʱֵ + */ +#define TMR3_GetCurrentTimer() R32_TMR3_COUNT + +/** + * @brief ؼܳʼ + * + * @param cap - ɼ + */ +void TMR3_EXTSingleCounterInit(CapModeTypeDef cap); + +/** + * @brief üͳС67108862 + * + * @param cyc - ͳС + */ +#define TMR3_CountOverflowCfg(cyc) (R32_TMR3_CNT_END = (cyc + 2)) + +/** + * @brief ȡǰֵ67108862 + * + * @return ǰֵ + */ +#define TMR3_GetCurrentCount() R32_TMR3_COUNT + +/** + * @brief PWM3 ͨ, 67108864 + * + * @param cyc - + */ +#define TMR3_PWMCycleCfg(cyc) (R32_TMR3_CNT_END = cyc) + +/** + * @brief PWM ʼ + * + * @param pr - select wave polar, refer to PWMX_PolarTypeDef + * @param ts - set pwm repeat times, refer to PWM_RepeatTsTypeDef + */ +void TMR3_PWMInit(PWMX_PolarTypeDef pr, PWM_RepeatTsTypeDef ts); + +/** + * @brief PWM3 Ч, 67108864 + * + * @param d - Ч + */ +#define TMR3_PWMActDataWidth(d) (R32_TMR3_FIFO = d) + +/** + * @brief CAP3 ׽ƽʱ, 33554432 + * + * @param cyc - ׽ƽʱ + */ +#define TMR3_CAPTimeoutCfg(cyc) (R32_TMR3_CNT_END = cyc) + +/** + * @brief ⲿźŲ׽ܳʼ + * + * @param cap - select capture mode, refer to CapModeTypeDef + */ +void TMR3_CapInit(CapModeTypeDef cap); + +/** + * @brief ȡ + * + * @return + */ +#define TMR3_CAPGetData() R32_TMR3_FIFO + +/** + * @brief ȡǰѲݸ + * + * @return ǰѲݸ + */ +#define TMR3_CAPDataCounter() R8_TMR3_FIFO_COUNT + +/** + * @brief ر TMR3 + */ +#define TMR3_Disable() (R8_TMR3_CTRL_MOD &= ~RB_TMR_COUNT_EN) + +/** + * @brief TMR3 + */ +#define TMR3_Enable() (R8_TMR3_CTRL_MOD |= RB_TMR_COUNT_EN) + +/** + * @brief ж + * + * @param s - ʹ/ر + * @param f - refer to TMR interrupt bit define + */ +#define TMR3_ITCfg(s, f) ((s) ? (R8_TMR3_INTER_EN |= f) : (R8_TMR3_INTER_EN &= ~f)) + +/** + * @brief жϱ־ + * + * @param f - refer to TMR interrupt bit define + */ +#define TMR3_ClearITFlag(f) (R8_TMR3_INT_FLAG = f) + +/** + * @brief ѯжϱ־״̬ + * + * @param f - refer to TMR interrupt bit define + */ +#define TMR3_GetITFlag(f) (R8_TMR3_INT_FLAG & f) + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_TIMER_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_uart.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_uart.h new file mode 100644 index 0000000..75f8244 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_uart.h @@ -0,0 +1,412 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_uart.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_UART_H__ +#define __CH58x_UART_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LINE error and status define + */ +#define STA_ERR_BREAK RB_LSR_BREAK_ERR // ݼ +#define STA_ERR_FRAME RB_LSR_FRAME_ERR // ֡ +#define STA_ERR_PAR RB_LSR_PAR_ERR // żУλ +#define STA_ERR_FIFOOV RB_LSR_OVER_ERR // + +#define STA_TXFIFO_EMP RB_LSR_TX_FIFO_EMP // ǰFIFOգԼ䷢ +#define STA_TXALL_EMP RB_LSR_TX_ALL_EMP // ǰзݶ +#define STA_RECV_DATA RB_LSR_DATA_RDY // ǰнյ + +/** + * @brief Configuration UART TrigByte num + */ +typedef enum +{ + UART_1BYTE_TRIG = 0, // 1ֽڴ + UART_2BYTE_TRIG, // 2ֽڴ + UART_4BYTE_TRIG, // 4ֽڴ + UART_7BYTE_TRIG, // 7ֽڴ + +} UARTByteTRIGTypeDef; + +/** + * @brief Ĭϳʼ + */ +void UART0_DefInit(void); + +/** + * @brief ڲ + * + * @param baudrate - + */ +void UART0_BaudRateCfg(uint32_t baudrate); + +/** + * @brief ֽڴж + * + * @param b - ֽ refer to UARTByteTRIGTypeDef + */ +void UART0_ByteTrigCfg(UARTByteTRIGTypeDef b); + +/** + * @brief ж + * + * @param s - жϿ״̬ǷʹӦж + * @param i - ж + * RB_IER_MODEM_CHG - ƽ״̬仯жʹλ UART0 ֧֣ + * RB_IER_LINE_STAT - ·״̬ж + * RB_IER_THR_EMPTY - ͱּĴж + * RB_IER_RECV_RDY - ж + */ +void UART0_INTCfg(FunctionalState s, uint8_t i); + +/** + * @brief λ + */ +void UART0_Reset(void); + +/** + * @brief ǰFIFO + */ +#define UART0_CLR_RXFIFO() (R8_UART0_FCR |= RB_FCR_RX_FIFO_CLR) + +/** + * @brief ǰFIFO + */ +#define UART0_CLR_TXFIFO() (R8_UART0_FCR |= RB_FCR_TX_FIFO_CLR) + +/** + * @brief ȡǰжϱ־ + * + * @return ǰжϱ־ + */ +#define UART0_GetITFlag() (R8_UART0_IIR & RB_IIR_INT_MASK) + +/** + * @brief ȡǰͨѶ״̬ + * + * @return refer to LINE error and status define + */ +#define UART0_GetLinSTA() (R8_UART0_LSR) + +/** + * @brief ڵֽڷ + * + * @param b ͵ֽ + */ +#define UART0_SendByte(b) (R8_UART0_THR = b) + +/** + * @brief ڶֽڷ + * + * @param buf - ͵׵ַ + * @param l - ͵ݳ + */ +void UART0_SendString(uint8_t *buf, uint16_t l); + +/** + * @brief ڶȡֽ + * + * @return ȡĵֽ + */ +#define UART0_RecvByte() (R8_UART0_RBR) + +/** + * @brief ڶȡֽ + * + * @param buf - ȡݴŻ׵ַ + * + * @return ȡݳ + */ +uint16_t UART0_RecvString(uint8_t *buf); + +/** + * @brief Ĭϳʼ + */ +void UART1_DefInit(void); + +/** + * @brief ڲ + * + * @param baudrate - + */ +void UART1_BaudRateCfg(uint32_t baudrate); + +/** + * @brief ֽڴж + * + * @param b - ֽ refer to UARTByteTRIGTypeDef + */ +void UART1_ByteTrigCfg(UARTByteTRIGTypeDef b); + +/** + * @brief ж + * + * @param s - жϿ״̬ǷʹӦж + * @param i - ж + * RB_IER_MODEM_CHG - ƽ״̬仯жʹλ UART0 ֧֣ + * RB_IER_LINE_STAT - ·״̬ж + * RB_IER_THR_EMPTY - ͱּĴж + * RB_IER_RECV_RDY - ж + */ +void UART1_INTCfg(FunctionalState s, uint8_t i); + +/** + * @brief λ + */ +void UART1_Reset(void); + +/** + * @brief ǰFIFO + */ +#define UART1_CLR_RXFIFO() (R8_UART1_FCR |= RB_FCR_RX_FIFO_CLR) + +/** + * @brief ǰFIFO + */ +#define UART1_CLR_TXFIFO() (R8_UART1_FCR |= RB_FCR_TX_FIFO_CLR) + +/** + * @brief ȡǰжϱ־ + * + * @return ǰжϱ־ + */ +#define UART1_GetITFlag() (R8_UART1_IIR & RB_IIR_INT_MASK) + +/** + * @brief ȡǰͨѶ״̬ + * + * @return refer to LINE error and status define + */ +#define UART1_GetLinSTA() (R8_UART1_LSR) + +/** + * @brief ڵֽڷ + * + * @param b ͵ֽ + */ +#define UART1_SendByte(b) (R8_UART1_THR = b) + +/** + * @brief ڶֽڷ + * + * @param buf - ͵׵ַ + * @param l - ͵ݳ + */ +void UART1_SendString(uint8_t *buf, uint16_t l); + +/** + * @brief ڶȡֽ + * + * @return ȡĵֽ + */ +#define UART1_RecvByte() (R8_UART1_RBR) + +/** + * @brief ڶȡֽ + * + * @param buf - ȡݴŻ׵ַ + * + * @return ȡݳ + */ +uint16_t UART1_RecvString(uint8_t *buf); + +/** + * @brief Ĭϳʼ + */ +void UART2_DefInit(void); + +/** + * @brief ڲ + * + * @param baudrate - + */ +void UART2_BaudRateCfg(uint32_t baudrate); + +/** + * @brief ֽڴж + * + * @param b - ֽ refer to UARTByteTRIGTypeDef + */ +void UART2_ByteTrigCfg(UARTByteTRIGTypeDef b); + +/** + * @brief ж + * + * @param s - жϿ״̬ǷʹӦж + * @param i - ж + * RB_IER_MODEM_CHG - ƽ״̬仯жʹλ UART0 ֧֣ + * RB_IER_LINE_STAT - ·״̬ж + * RB_IER_THR_EMPTY - ͱּĴж + * RB_IER_RECV_RDY - ж + */ +void UART2_INTCfg(FunctionalState s, uint8_t i); + +/** + * @brief λ + */ +void UART2_Reset(void); + +/** + * @brief ǰFIFO + */ +#define UART2_CLR_RXFIFO() (R8_UART2_FCR |= RB_FCR_RX_FIFO_CLR) + +/** + * @brief ǰFIFO + */ +#define UART2_CLR_TXFIFO() (R8_UART2_FCR |= RB_FCR_TX_FIFO_CLR) + +/** + * @brief ȡǰжϱ־ + * + * @return ǰжϱ־ + */ +#define UART2_GetITFlag() (R8_UART2_IIR & RB_IIR_INT_MASK) + +/** + * @brief ȡǰͨѶ״̬ + * + * @return refer to LINE error and status define + */ +#define UART2_GetLinSTA() (R8_UART2_LSR) + +/** + * @brief ڵֽڷ + * + * @param b ͵ֽ + */ +#define UART2_SendByte(b) (R8_UART2_THR = b) + +/** + * @brief ڶֽڷ + * + * @param buf - ͵׵ַ + * @param l - ͵ݳ + */ +void UART2_SendString(uint8_t *buf, uint16_t l); + +/** + * @brief ڶȡֽ + * + * @return ȡĵֽ + */ +#define UART2_RecvByte() (R8_UART2_RBR) + +/** + * @brief ڶȡֽ + * + * @param buf - ȡݴŻ׵ַ + * + * @return ȡݳ + */ +uint16_t UART2_RecvString(uint8_t *buf); + +/** + * @brief Ĭϳʼ + */ +void UART3_DefInit(void); + +/** + * @brief ڲ + * + * @param baudrate - + */ +void UART3_BaudRateCfg(uint32_t baudrate); + +/** + * @brief ֽڴж + * + * @param b - ֽ refer to UARTByteTRIGTypeDef + */ +void UART3_ByteTrigCfg(UARTByteTRIGTypeDef b); + +/** + * @brief ж + * + * @param s - жϿ״̬ǷʹӦж + * @param i - ж + * RB_IER_MODEM_CHG - ƽ״̬仯жʹλ UART0 ֧֣ + * RB_IER_LINE_STAT - ·״̬ж + * RB_IER_THR_EMPTY - ͱּĴж + * RB_IER_RECV_RDY - ж + */ +void UART3_INTCfg(FunctionalState s, uint8_t i); + +/** + * @brief λ + */ +void UART3_Reset(void); + +/** + * @brief ǰFIFO + */ +#define UART3_CLR_RXFIFO() (R8_UART3_FCR |= RB_FCR_RX_FIFO_CLR) + +/** + * @brief ǰFIFO + */ +#define UART3_CLR_TXFIFO() (R8_UART3_FCR |= RB_FCR_TX_FIFO_CLR) + +/** + * @brief ȡǰжϱ־ + * + * @return ǰжϱ־ + */ +#define UART3_GetITFlag() (R8_UART3_IIR & RB_IIR_INT_MASK) + +/** + * @brief ȡǰͨѶ״̬ + * + * @return refer to LINE error and status define + */ +#define UART3_GetLinSTA() (R8_UART3_LSR) + +/** + * @brief ڵֽڷ + * + * @param b ͵ֽ + */ +#define UART3_SendByte(b) (R8_UART3_THR = b) + +/** + * @brief ڶֽڷ + * + * @param buf - ͵׵ַ + * @param l - ͵ݳ + */ +void UART3_SendString(uint8_t *buf, uint16_t l); + +/** + * @brief ڶȡֽ + * + * @return ȡĵֽ + */ +#define UART3_RecvByte() (R8_UART3_RBR) + +/** + * @brief ڶȡֽ + * + * @param buf - ȡݴŻ׵ַ + * + * @return ȡݳ + */ +uint16_t UART3_RecvString(uint8_t *buf); + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_UART_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_usbhost.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_usbhost.h new file mode 100644 index 0000000..78b92b7 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_usbhost.h @@ -0,0 +1,349 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : CH57x_usbhost.h + * Author : WCH + * Version : V1.2 + * Date : 2021/11/17 + * Description + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ + +#ifndef __CH58x_USBHOST_H__ +#define __CH58x_USBHOST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if DISK_LIB_ENABLE + #if DISK_WITHOUT_USB_HUB + /* ʹUļϵͳU̹USBhub棬Ҫر涨 */ + #define FOR_ROOT_UDISK_ONLY + #endif + /* ʹUļϵͳ⣬Ҫ涨, ʹر */ + #define DISK_BASE_BUF_LEN 512 /* ĬϵĴݻСΪ512ֽ,ѡΪ20484096֧ijЩU,Ϊ0ֹ.Hļж建ӦópDISK_BASE_BUFָ */ +#endif + +// ӳ򷵻״̬ +#define ERR_SUCCESS 0x00 // ɹ +#define ERR_USB_CONNECT 0x15 /* ⵽USB豸¼,Ѿ */ +#define ERR_USB_DISCON 0x16 /* ⵽USB豸Ͽ¼,ѾϿ */ +#define ERR_USB_BUF_OVER 0x17 /* USB̫໺ */ +#define ERR_USB_DISK_ERR 0x1F /* USB洢ʧ,ڳʼʱUSB洢֧,ڶдпǴ𻵻ѾϿ */ +#define ERR_USB_TRANSFER 0x20 /* NAK/STALLȸ0x20~0x2F */ +#define ERR_USB_UNSUPPORT 0xFB /* ֵ֧USB豸*/ +#define ERR_USB_UNKNOWN 0xFE /* 豸*/ +#define ERR_AOA_PROTOCOL 0x41 /* Э汾 */ + +/*USB豸Ϣ,֧1豸*/ +#define ROOT_DEV_DISCONNECT 0 +#define ROOT_DEV_CONNECTED 1 +#define ROOT_DEV_FAILED 2 +#define ROOT_DEV_SUCCESS 3 +#define DEV_TYPE_KEYBOARD (USB_DEV_CLASS_HID | 0x20) +#define DEV_TYPE_MOUSE (USB_DEV_CLASS_HID | 0x30) +#define DEF_AOA_DEVICE 0xF0 +#define DEV_TYPE_UNKNOW 0xFF + +/* +Լ: USB豸ַ(οUSB_DEVICE_ADDR) +ֵַ 豸λ +0x02 Root-HUBµUSB豸ⲿHUB +0x1x Root-HUBµⲿHUBĶ˿xµUSB豸,xΪ1~n +*/ +#define HUB_MAX_PORTS 4 +#define WAIT_USB_TOUT_200US 800 // ȴUSBжϳʱʱ + +typedef struct +{ + uint8_t DeviceStatus; // 豸״̬,0-豸,1-豸δʼ,2-豸ʼöʧ,3-豸ҳʼöٳɹ + uint8_t DeviceAddress; // 豸USBַ + uint8_t DeviceSpeed; // 0Ϊ,0Ϊȫ + uint8_t DeviceType; // 豸 + uint16_t DeviceVID; + uint16_t DevicePID; + uint8_t GpVar[4]; // ͨñŶ˵ + uint8_t GpHUBPortNum; // ͨñ,HUBʾHUB˿ +} _RootHubDev; + +typedef struct +{ + UINT8 DeviceStatus; // 豸״̬,0-豸,1-豸δʼ,2-豸ʼöʧ,3-豸ҳʼöٳɹ + UINT8 DeviceAddress; // 豸USBַ + UINT8 DeviceSpeed; // 0Ϊ,0Ϊȫ + UINT8 DeviceType; // 豸 + UINT16 DeviceVID; + UINT16 DevicePID; + UINT8 GpVar[4]; // ͨñ +} _DevOnHubPort; // ٶ:1ⲿHUB,ÿⲿHUBHUB_MAX_PORTS˿(˲) + +extern _RootHubDev ThisUsbDev; +extern _DevOnHubPort DevOnHubPort[HUB_MAX_PORTS]; // ٶ:1ⲿHUB,ÿⲿHUBHUB_MAX_PORTS˿(˲) +extern uint8_t UsbDevEndp0Size; // USB豸Ķ˵0ߴ */ +extern uint8_t FoundNewDev; + +extern uint8_t *pHOST_RX_RAM_Addr; +extern uint8_t *pHOST_TX_RAM_Addr; + +extern _RootHubDev ThisUsb2Dev; +extern _DevOnHubPort DevOnU2HubPort[HUB_MAX_PORTS]; // ٶ:1ⲿHUB,ÿⲿHUBHUB_MAX_PORTS˿(˲) +extern uint8_t Usb2DevEndp0Size; // USB豸Ķ˵0ߴ */ +extern uint8_t FoundNewU2Dev; + +extern uint8_t *pU2HOST_RX_RAM_Addr; +extern uint8_t *pU2HOST_TX_RAM_Addr; + +#define pSetupReq ((PUSB_SETUP_REQ)pHOST_TX_RAM_Addr) +#define pU2SetupReq ((PUSB_SETUP_REQ)pU2HOST_TX_RAM_Addr) +extern uint8_t Com_Buffer[]; +extern uint8_t U2Com_Buffer[]; + +/* ΪUSB */ +extern const uint8_t SetupGetDevDescr[]; // ȡ豸*/ +extern const uint8_t SetupGetCfgDescr[]; // ȡ*/ +extern const uint8_t SetupSetUsbAddr[]; // USBַ*/ +extern const uint8_t SetupSetUsbConfig[]; // USB*/ +extern const uint8_t SetupSetUsbInterface[]; // USBӿ*/ +extern const uint8_t SetupClrEndpStall[]; // ˵STALL*/ + +extern const uint8_t SetupGetU2DevDescr[]; // ȡ豸*/ +extern const uint8_t SetupGetU2CfgDescr[]; // ȡ*/ +extern const uint8_t SetupSetUsb2Addr[]; // USBַ*/ +extern const uint8_t SetupSetUsb2Config[]; // USB*/ +extern const uint8_t SetupSetUsb2Interface[]; // USBӿ*/ +extern const uint8_t SetupClrU2EndpStall[]; // ˵STALL*/ + +/** + * @brief رROOT-HUB˿,ʵӲѾԶر,˴ֻһЩṹ״̬ + */ +void DisableRootHubPort(void); + +/** + * @brief ROOT-HUB״̬,ROOT-HUB˿ڵ豸¼ + * 豸γ,еDisableRootHubPort(),˿ڹر,¼,Ӧ˿ڵ״̬λ + * + * @return ERR_SUCCESSΪû,ERR_USB_CONNECTΪ⵽,ERR_USB_DISCONΪ⵽Ͽ + */ +uint8_t AnalyzeRootHub(void); + +/** + * @brief USBǰUSB豸ַ + * + * @param addr - USB豸ַ + */ +void SetHostUsbAddr(uint8_t addr); + +/** + * @brief õǰUSBٶ + * + * @param FullSpeed - USBٶ + */ +void SetUsbSpeed(uint8_t FullSpeed); + +/** + * @brief ⵽豸,λ,Ϊö豸׼,ΪĬΪȫ + */ +void ResetRootHubPort(void); + +/** + * @brief ʹROOT-HUB˿,ӦbUH_PORT_EN1˿,豸Ͽܵ·ʧ + * + * @return ERR_SUCCESSΪ⵽,ERR_USB_DISCONΪ + */ +uint8_t EnableRootHubPort(void); + +/** + * @brief ȴUSBж + * + * @return ERR_SUCCESS ݽջ߷ͳɹ,ERR_USB_UNKNOWN ݽջ߷ʧ + */ +uint8_t WaitUSB_Interrupt(void); + +/** + * @brief ,ĿĶ˵ַ/PID,ͬ־,20uSΪλNAKʱ(0,0xFFFF),0ɹ,ʱ/ + * ӳ,ʵӦ,Ϊṩٶ,ӦöԱӳŻ + * + * @param endp_pid - ƺ͵ַ, 4λtoken_pid, 4λǶ˵ַ + * @param tog - ͬ־ + * @param timeout - ʱʱ + * + * @return ERR_USB_UNKNOWN ʱӲ쳣 + * ERR_USB_DISCON 豸Ͽ + * ERR_USB_CONNECT 豸 + * ERR_SUCCESS + */ +uint8_t USBHostTransact(uint8_t endp_pid, uint8_t tog, uint32_t timeout); + +/** + * @brief ִпƴ,8ֽpSetupReq,DataBufΪѡշ + * + * @param DataBuf - Ҫպͷ,ôDataBufָЧڴź + * @param RetLen - ʵʳɹշܳȱRetLenָֽڱ + * + * @return ERR_USB_BUF_OVER IN״̬׶γ + * ERR_SUCCESS ݽɹ + */ +uint8_t HostCtrlTransfer(uint8_t *DataBuf, uint8_t *RetLen); + +/** + * @brief ƿƴ + * + * @param pReqPkt - ַ + */ +void CopySetupReqPkg(const uint8_t *pReqPkt); + +/** + * @brief ȡ豸, pHOST_TX_RAM_Addr + * + * @return ERR_USB_BUF_OVER ȴ + * ERR_SUCCESS ɹ + */ +uint8_t CtrlGetDeviceDescr(void); + +/** + * @brief ȡ, pHOST_TX_RAM_Addr + * + * @return ERR_USB_BUF_OVER ȴ + * ERR_SUCCESS ɹ + */ +uint8_t CtrlGetConfigDescr(void); + +/** + * @brief USB豸ַ + * + * @param addr - 豸ַ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsbAddress(uint8_t addr); + +/** + * @brief USB豸 + * + * @param cfg - ֵ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsbConfig(uint8_t cfg); + +/** + * @brief ˵STALL + * + * @param endp - ˵ַ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlClearEndpStall(uint8_t endp); + +/** + * @brief USB豸ӿ + * + * @param cfg - ֵ + * + * @return ERR_SUCCESS ɹ + */ +uint8_t CtrlSetUsbIntercace(uint8_t cfg); + +/** + * @brief USBܳʼ + */ +void USB_HostInit(void); +uint8_t EnumAllHubPort(void);// öROOT-HUB˿ⲿHUBĶUSB豸 +void SelectHubPort(uint8_t HubPortIndex); // HubPortIndex=0ѡָROOT-HUB˿,ѡָROOT-HUB˿ڵⲿHUBָ˿ +uint16_t SearchTypeDevice(uint8_t type); // ROOT-HUBԼⲿHUB˿ָ͵豸ڵĶ˿ں,˿ںΪ0xFFFFδ. +uint8_t SETorOFFNumLock(uint8_t *buf); // NumLockĵж + +void DisableRootU2HubPort(void); // رROOT-U2HUB˿,ʵӲѾԶر,˴ֻһЩṹ״̬ +uint8_t AnalyzeRootU2Hub(void); // ROOT-U2HUB״̬,ROOT-U2HUB˿ڵ豸¼ +// ERR_SUCCESSΪû,ERR_USB_CONNECTΪ⵽,ERR_USB_DISCONΪ⵽Ͽ +void SetHostUsb2Addr(uint8_t addr); // USBǰUSB豸ַ +void SetUsb2Speed(uint8_t FullSpeed); // õǰUSBٶ +void ResetRootU2HubPort(void); // ⵽豸,λӦ˿ڵ,Ϊö豸׼,ΪĬΪȫ +uint8_t EnableRootU2HubPort(void); // ʹROOT-HUB˿,ӦbUH_PORT_EN1˿,豸Ͽܵ·ʧ +void SelectU2HubPort(uint8_t HubPortIndex); // HubPortIndex=0ѡָROOT-HUB˿,ѡָROOT-HUB˿ڵⲿHUBָ˿ +uint8_t WaitUSB2_Interrupt(void); // ȴUSBж +// ,ĿĶ˵ַ/PID,ͬ־,20uSΪλNAKʱ(0,0xFFFF),0ɹ,ʱ/ +uint8_t USB2HostTransact(uint8_t endp_pid, uint8_t tog, UINT32 timeout); // endp_pid: 4λtoken_pid, 4λǶ˵ַ +uint8_t U2HostCtrlTransfer(uint8_t *DataBuf, uint8_t *RetLen); // ִпƴ,8ֽpSetupReq,DataBufΪѡշ +// Ҫպͷ,ôDataBufָЧڴź,ʵʳɹշܳȷرReqLenָֽڱ + +void CopyU2SetupReqPkg(const uint8_t *pReqPkt); // ƿƴ +uint8_t CtrlGetU2DeviceDescr(void); // ȡ豸, pHOST_TX_RAM_Addr +uint8_t CtrlGetU2ConfigDescr(void); // ȡ, pHOST_TX_RAM_Addr +uint8_t CtrlSetUsb2Address(uint8_t addr); // USB豸ַ +uint8_t CtrlSetUsb2Config(uint8_t cfg); // USB豸 +uint8_t CtrlClearU2EndpStall(uint8_t endp); // ˵STALL +uint8_t CtrlSetUsb2Intercace(uint8_t cfg); // USB豸ӿ + +void USB2_HostInit(void); // ʼUSB + +/*************************************************************/ + +/** + * @brief ʼָROOT-HUB˿ڵUSB豸 + * + * @return + */ +uint8_t InitRootDevice(void); + +/** + * @brief ȡHID豸,TxBuffer + * + * @return + */ +uint8_t CtrlGetHIDDeviceReport(uint8_t infc); + +/** + * @brief ȡHUB,Com_Buffer + * + * @return + */ +uint8_t CtrlGetHubDescr(void); + +/** + * @brief ѯHUB˿״̬,Com_Buffer + * + * @param HubPortIndex - ˿ں + * + * @return + */ +uint8_t HubGetPortStatus(uint8_t HubPortIndex); + +/** + * @brief HUB˿ + * + * @param HubPortIndex - ˿ں + * @param FeatureSelt - ˿ + * + * @return + */ +uint8_t HubSetPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt); + +/** + * @brief HUB˿ + * + * @param HubPortIndex - ˿ں + * @param FeatureSelt - ˿ + * + * @return + */ +uint8_t HubClearPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt); + +uint8_t InitRootU2Device(void); +uint8_t EnumAllU2HubPort(void); +uint16_t U2SearchTypeDevice(uint8_t type); +uint8_t U2SETorOFFNumLock(uint8_t *buf); + +uint8_t CtrlGetU2HIDDeviceReport(uint8_t infc); // HIDSET_IDLEGET_REPORT +uint8_t CtrlGetU2HubDescr(void); // ȡHUB,TxBuffer +uint8_t U2HubGetPortStatus(uint8_t HubPortIndex); // ѯHUB˿״̬,TxBuffer +uint8_t U2HubSetPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt); // HUB˿ +uint8_t U2HubClearPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt); // HUB˿ + +#ifdef __cplusplus +} +#endif + +#endif // __CH58x_USBHOST_H__ diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/ISP583.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/ISP583.h new file mode 100644 index 0000000..e228c07 --- /dev/null +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/ISP583.h @@ -0,0 +1,190 @@ +/* CH583 Flash-ROM & Data-Flash */ +/* Website: http://wch.cn */ +/* Email: tech@wch.cn */ +/* Author: W.ch 2020.06 */ +/* V1.0 FlashROM library for USER/BOOT */ +/* for the target in USER code area on the chip divided into USER code area and BOOT area */ +/* ھûоƬĿΪû + ûбãIAPдҲбãû룩 */ + +/* Flash-ROM feature: + for store program code, support block erasing, dword and page writing, dword verifying, unit for Length is byte, + minimal quantity for write or verify is one dword (4-bytes), + 256 bytes/page for writing, FLASH_ROM_WRITE support one dword or more dword writing, but multiple of 256 is the best, + 4KB (4096 bytes) bytes/block for erasing, so multiple of 4096 is the best */ + +/* Data-Flash(EEPROM) feature: + for store data, support block erasing, byte and page writing, byte reading, + minimal quantity for write or read is one byte, + 256 bytes/page for writing, EEPROM_WRITE support one byte or more byte writing, but multiple of 256 is the best, + 0.25KB/4KB (256/4096 bytes) bytes/block for erasing, so multiple of 256 or 4096 is the best */ + + +#ifndef EEPROM_PAGE_SIZE +#define EEPROM_PAGE_SIZE 256 // Flash-ROM & Data-Flash page size for writing +#define EEPROM_BLOCK_SIZE 4096 // Flash-ROM & Data-Flash block size for erasing +#define EEPROM_MIN_ER_SIZE EEPROM_PAGE_SIZE // Data-Flash minimal size for erasing +//#define EEPROM_MIN_ER_SIZE EEPROM_BLOCK_SIZE // Flash-ROM minimal size for erasing +#define EEPROM_MIN_WR_SIZE 1 // Data-Flash minimal size for writing +#define EEPROM_MAX_SIZE 0x8000 // Data-Flash maximum size, 32KB +#endif +#ifndef FLASH_MIN_WR_SIZE +#define FLASH_MIN_WR_SIZE 4 // Flash-ROM minimal size for writing +#endif +#ifndef FLASH_ROM_MAX_SIZE +#define FLASH_ROM_MAX_SIZE 0x070000 // Flash-ROM maximum program size, 448KB +#endif + +#ifndef CMD_FLASH_ROM_SW_RESET +// CMD_* for caller from FlashROM or RAM, auto execute CMD_FLASH_ROM_SW_RESET before command + +#define CMD_FLASH_ROM_START_IO 0x00 // start FlashROM I/O, without parameter +#define CMD_FLASH_ROM_SW_RESET 0x04 // software reset FlashROM, without parameter +#define CMD_GET_ROM_INFO 0x06 // get information from FlashROM, parameter @Address,Buffer +#define CMD_GET_UNIQUE_ID 0x07 // get 64 bit unique ID, parameter @Buffer +#define CMD_FLASH_ROM_PWR_DOWN 0x0D // power-down FlashROM, without parameter +#define CMD_FLASH_ROM_PWR_UP 0x0C // power-up FlashROM, without parameter +#define CMD_FLASH_ROM_LOCK 0x08 // lock(protect)/unlock FlashROM data block, return 0 if success, parameter @StartAddr +// StartAddr: 0=unlock all, 1=lock boot code, 3=lock all code and data + +#define CMD_EEPROM_ERASE 0x09 // erase Data-Flash block, return 0 if success, parameter @StartAddr,Length +#define CMD_EEPROM_WRITE 0x0A // write Data-Flash data block, return 0 if success, parameter @StartAddr,Buffer,Length +#define CMD_EEPROM_READ 0x0B // read Data-Flash data block, parameter @StartAddr,Buffer,Length +#define CMD_FLASH_ROM_ERASE 0x01 // erase FlashROM block, return 0 if success, parameter @StartAddr,Length +#define CMD_FLASH_ROM_WRITE 0x02 // write FlashROM data block, minimal block is dword, return 0 if success, parameter @StartAddr,Buffer,Length +#define CMD_FLASH_ROM_VERIFY 0x03 // read FlashROM data block, minimal block is dword, return 0 if success, parameter @StartAddr,Buffer,Length +#endif + +#define ROM_CFG_MAC_ADDR 0x7F018 // address for MAC address information +#define ROM_CFG_BOOT_INFO 0x7DFF8 // address for BOOT information + +/** + * @brief execute Flash/EEPROM command, caller from FlashROM or RAM + * + * @param cmd - CMD_* for caller from FlashROM or RAM. + * @param StartAddr - Address of the data to be process. + * @param Buffer - Pointer to the buffer where data should be process, Must be aligned to 4 bytes. + * @param Length - Size of data to be process, in bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +extern uint32_t FLASH_EEPROM_CMD( uint8_t cmd, uint32_t StartAddr, void *Buffer, uint32_t Length ); + +/** + * @brief start FlashROM I/O + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define FLASH_ROM_START_IO( ) FLASH_EEPROM_CMD( CMD_FLASH_ROM_START_IO, 0, NULL, 0 ) + +/** + * @brief software reset FlashROM + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define FLASH_ROM_SW_RESET( ) FLASH_EEPROM_CMD( CMD_FLASH_ROM_SW_RESET, 0, NULL, 0 ) + +/** + * @brief get 6 bytes MAC address + * + * @param Buffer - Pointer to the buffer where data should be stored, Must be aligned to 4 bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define GetMACAddress(Buffer) FLASH_EEPROM_CMD( CMD_GET_ROM_INFO, ROM_CFG_MAC_ADDR, Buffer, 0 ) + +/** + * @brief get 8 bytes BOOT information + * + * @param Buffer - Pointer to the buffer where data should be stored, Must be aligned to 4 bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define GET_BOOT_INFO(Buffer) FLASH_EEPROM_CMD( CMD_GET_ROM_INFO, ROM_CFG_BOOT_INFO, Buffer, 0 ) + +/** + * @brief get 64 bit unique ID + * + * @param Buffer - Pointer to the buffer where data should be stored, Must be aligned to 4 bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define GET_UNIQUE_ID(Buffer) FLASH_EEPROM_CMD( CMD_GET_UNIQUE_ID, 0, Buffer, 0 ) + +/** + * @brief power-down FlashROM + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define FLASH_ROM_PWR_DOWN( ) FLASH_EEPROM_CMD( CMD_FLASH_ROM_PWR_DOWN, 0, NULL, 0 ) + +/** + * @brief power-up FlashROM + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define FLASH_ROM_PWR_UP( ) FLASH_EEPROM_CMD( CMD_FLASH_ROM_PWR_UP, 0, NULL, 0 ) + +/** + * @brief read Data-Flash data block + * + * @param StartAddr - Address of the data to be read. + * @param Buffer - Pointer to the buffer where data should be stored, Must be aligned to 4 bytes. + * @param Length - Size of data to be read, in bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define EEPROM_READ(StartAddr,Buffer,Length) FLASH_EEPROM_CMD( CMD_EEPROM_READ, StartAddr, Buffer, Length ) + +/** + * + * @param StartAddr - Address of the data to be erased. + * @param Length - Size of data to be erased, in bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define EEPROM_ERASE(StartAddr,Length) FLASH_EEPROM_CMD( CMD_EEPROM_ERASE, StartAddr, NULL, Length ) + +/** + * @brief write Data-Flash data block + * + * @param StartAddr - Address of the data to be written. + * @param Buffer - Pointer to the source buffer, Must be aligned to 4 bytes. + * @param Length - Size of data to be written, in bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define EEPROM_WRITE(StartAddr,Buffer,Length) FLASH_EEPROM_CMD( CMD_EEPROM_WRITE, StartAddr, Buffer, Length ) + +/** + * @brief erase FlashROM block + * + * @param StartAddr - Address of the data to be erased. + * @param Length - Size of data to be erased, in bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define FLASH_ROM_ERASE(StartAddr,Length) FLASH_EEPROM_CMD( CMD_FLASH_ROM_ERASE, StartAddr, NULL, Length ) + +/** + * @brief write FlashROM data block, minimal block is dword. + * + * @param StartAddr - Address of the data to be written. + * @param Buffer - Pointer to the source buffer, Must be aligned to 4 bytes. + * @param Length - Size of data to be written, in bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define FLASH_ROM_WRITE(StartAddr,Buffer,Length) FLASH_EEPROM_CMD( CMD_FLASH_ROM_WRITE, StartAddr, Buffer, Length ) + +/** + * @brief verify FlashROM data block, minimal block is dword. + * + * @param StartAddr - Address of the data to verify. + * @param Buffer - Pointer to the source buffer, Must be aligned to 4 bytes. + * @param Length - Size of data to verify, in bytes. + * + * @return 0-SUCCESS (!0)-FAILURE + */ +#define FLASH_ROM_VERIFY(StartAddr,Buffer,Length) FLASH_EEPROM_CMD( CMD_FLASH_ROM_VERIFY, StartAddr, Buffer, Length ) + diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/libISP583.a b/CH5xx_ble_firmware_library/StdPeriphDriver/libISP583.a new file mode 100644 index 0000000..4191b26 Binary files /dev/null and b/CH5xx_ble_firmware_library/StdPeriphDriver/libISP583.a differ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..2f0a1ce --- /dev/null +++ b/COPYING @@ -0,0 +1,97 @@ +OPENBARE LICENTIE VAN DE EUROPESE UNIE v. 1.2. +EUPL © Europese Unie 2007, 2016 +Deze openbare licentie van de Europese Unie („EUPL”) is van toepassing op het werk (zoals hieronder gedefinieerd) dat onder de voorwaarden van deze licentie wordt verstrekt. Elk gebruik van het werk dat niet door deze licentie is toegestaan, is verboden (voor zover dit gebruik valt onder een recht van de houder van het auteursrecht op het werk). Het werk wordt verstrekt onder de voorwaarden van deze licentie wanneer de licentiegever (zoals hieronder gedefinieerd), direct volgend op de kennisgeving inzake het auteursrecht op het werk, de volgende kennisgeving opneemt: + In licentie gegeven krachtens de EUPL +of op een andere wijze zijn bereidheid te kennen heeft gegeven krachtens de EUPL in licentie te geven. + +1.Definities +In deze licentie wordt verstaan onder: +— „de licentie”:de onderhavige licentie; +— „het oorspronkelijke werk”:het werk dat of de software die door de licentiegever krachtens deze licentie wordt verspreid of medegedeeld, en dat/die beschikbaar is als broncode en, in voorkomend geval, ook als uitvoerbare code; +— „bewerkingen”:de werken of software die de licentiehouder kan creëren op grond van het oorspronkelijke werk of wijzigingen ervan. In deze licentie wordt niet gedefinieerd welke mate van wijziging of afhankelijkheid van het oorspronkelijke werk vereist is om een werk als een bewerking te kunnen aanmerken; dat wordt bepaald conform het auteursrecht dat van toepassing is in de in artikel 15 bedoelde staat; +— „het werk”:het oorspronkelijke werk of de bewerkingen ervan; +— „de broncode”:de voor mensen leesbare vorm van het werk, die het gemakkelijkste door mensen kan worden bestudeerd en gewijzigd; +— „de uitvoerbare code”:elke code die over het algemeen is gecompileerd en is bedoeld om door een computer als een programma te worden uitgevoerd; +— „de licentiegever”:de natuurlijke of rechtspersoon die het werk krachtens de licentie verspreidt of mededeelt; +— „bewerker(s)”:elke natuurlijke of rechtspersoon die het werk krachtens de licentie wijzigt of op een andere wijze bijdraagt tot de totstandkoming van een bewerking; +— „de licentiehouder” of „u”:elke natuurlijke of rechtspersoon die het werk onder de voorwaarden van de licentie gebruikt; — „verspreiding” of „mededeling”:het verkopen, geven, uitlenen, verhuren, verspreiden, mededelen, doorgeven, of op een andere wijze online of offline beschikbaar stellen van kopieën van het werk of het verlenen van toegang tot de essentiële functies ervan ten behoeve van andere natuurlijke of rechtspersonen. + +2.Draagwijdte van de uit hoofde van de licentie verleende rechten +De licentiegever verleent u hierbij een wereldwijde, royaltyvrije, niet-exclusieve, voor een sublicentie in aanmerking komende licentie, om voor de duur van het aan het oorspronkelijke werk verbonden auteursrecht, het volgende te doen: +— het werk in alle omstandigheden en voor ongeacht welk doel te gebruiken; +— het werk te verveelvoudigen; +— het werk te wijzigen en op grond van het werk bewerkingen te ontwikkelen; +— het werk aan het publiek mede te delen, waaronder het recht om het werk of kopieën ervan aan het publiek ter beschikking te stellen of te vertonen, en het werk, in voorkomend geval, in het openbaar uit te voeren; +— het werk of kopieën ervan te verspreiden; +— het werk of kopieën ervan uit te lenen en te verhuren; +— de rechten op het werk of op kopieën ervan in sublicentie te geven. +Deze rechten kunnen worden uitgeoefend met gebruikmaking van alle thans bekende of nog uit te vinden media, dragers en formaten, voor zover het toepasselijke recht dit toestaat. In de landen waar immateriële rechten van toepassing zijn, doet de licentiegever afstand van zijn recht op uitoefening van zijn immateriële rechten in de mate die door het toepasselijke recht wordt toegestaan teneinde een doeltreffende uitoefening van de bovenvermelde in licentie gegeven economische rechten mogelijk te maken. De licentiegever verleent de licentiehouder een royaltyvrij, niet-exclusief gebruiksrecht op alle octrooien van de licentiegever, voor zover dit noodzakelijk is om de uit hoofde van deze licentie verleende rechten op het werk te gebruiken. + +3.Mededeling van de broncode +De licentiegever kan het werk verstrekken in zijn broncode of als uitvoerbare code. Indien het werk als uitvoerbare code wordt verstrekt, verstrekt de licentiegever bij elke door hem verspreide kopie van het werk tevens een machinaal leesbare kopie van de broncode van het werk of geeft hij in een mededeling, volgende op de bij het werk gevoegde auteursrechtelijke kennisgeving, de plaats aan waar de broncode gemakkelijk en vrij toegankelijk is, zolang de licentiegever het werk blijft verspreiden of mededelen. + +4.Beperkingen van het auteursrecht +Geen enkele bepaling in deze licentie heeft ten doel de licentiehouder het recht te ontnemen een beroep te doen op een uitzondering op of een beperking van de exclusieve rechten van de rechthebbenden op het werk, of op de uitputting van die rechten of andere toepasselijke beperkingen daarvan. + +5.Verplichtingen van de licentiehouder +De verlening van de bovenvermelde rechten is onderworpen aan een aantal aan de licentiehouder opgelegde beperkingen en verplichtingen. Het gaat om de onderstaande verplichtingen. + +Attributierecht: de licentiehouder moet alle auteurs-, octrooi- of merkenrechtelijke kennisgevingen onverlet laten alsook alle kennisgevingen die naar de licentie en de afwijzing van garanties verwijzen. De licentiehouder moet een afschrift van deze kennisgevingen en een afschrift van de licentie bij elke kopie van het werk voegen die hij verspreidt of mededeelt. De licentiehouder moet in elke bewerking duidelijk aangeven dat het werk is gewijzigd, en eveneens de datum van wijziging vermelden. + +Copyleftclausule: wanneer de licentiehouder kopieën van het oorspronkelijke werk of bewerkingen verspreidt of mededeelt, geschiedt die verspreiding of mededeling onder de voorwaarden van deze licentie of van een latere versie van deze licentie, tenzij het oorspronkelijke werk uitdrukkelijk alleen onder deze versie van de licentie wordt verspreid — bijvoorbeeld door de mededeling „alleen EUPL v. 1.2”. De licentiehouder (die licentiegever wordt) kan met betrekking tot het werk of de bewerkingen geen aanvullende bepalingen of voorwaarden opleggen of stellen die de voorwaarden van de licentie wijzigen of beperken. + +Verenigbaarheidsclausule: wanneer de licentiehouder bewerkingen of kopieën ervan verspreidt of mededeelt die zijn gebaseerd op het werk en op een ander werk dat uit hoofde van een verenigbare licentie in licentie is gegeven, kan die verspreiding of mededeling geschieden onder de voorwaarden van deze verenigbare licentie. Voor de toepassing van deze clausule wordt onder „verenigbare licentie” verstaan, de licenties die in het aanhangsel bij deze licentie zijn opgesomd. Indien de verplichtingen van de licentiehouder uit hoofde van de verenigbare licentie in strijd zijn met diens verplichtingen uit hoofde van deze licentie, hebben de verplichtingen van de verenigbare licentie voorrang. + +Verstrekking van de broncode: bij de verspreiding of mededeling van kopieën van het werk verstrekt de licentiehouder een machinaal leesbare kopie van de broncode of geeft hij aan waar deze broncode gemakkelijk en vrij toegankelijk is, zolang de licentiehouder het werk blijft verspreiden of mededelen. + +Juridische bescherming: deze licentie verleent geen toestemming om handelsnamen, handelsmerken, dienstmerken of namen van de licentiegever te gebruiken, behalve wanneer dit op grond van een redelijk en normaal gebruik noodzakelijk is om de oorsprong van het werk te beschrijven en de inhoud van de auteursrechtelijke kennisgeving te herhalen. + +6.Auteursketen +De oorspronkelijke licentiegever garandeert dat hij houder is van het hierbij verleende auteursrecht op het oorspronkelijke werk dan wel dat dit hem in licentie is gegeven en dat hij de bevoegdheid heeft de licentie te verlenen. Elke bewerker garandeert dat hij houder is van het auteursrecht op de door hem aan het werk aangebrachte wijzigingen dan wel dat dit hem in licentie is gegeven en dat hij de bevoegdheid heeft de licentie te verlenen. Telkens wanneer u de licentie aanvaardt, verlenen de oorspronkelijke licentiegever en de opeenvolgende bewerkers u een licentie op hun bijdragen aan het werk onder de voorwaarden van deze licentie. + +7.Uitsluiting van garantie +Het werk is een werk in ontwikkeling, dat voortdurend door vele bewerkers wordt verbeterd. Het is een onvoltooid werk, dat bijgevolg nog tekortkomingen of programmeerfouten („bugs”) kan vertonen, die onlosmakelijk verbonden zijn met dit soort ontwikkeling. Om die reden wordt het werk op grond van de licentie verstrekt „zoals het is” en zonder enige garantie met betrekking tot het werk te geven, met inbegrip van, maar niet beperkt tot garanties met betrekking tot de verhandelbaarheid, de geschiktheid voor een specifiek doel, de afwezigheid van tekortkomingen of fouten, de nauwkeurigheid, de eerbiediging van andere intellectuele-eigendomsrechten dan het in artikel 6 van deze licentie bedoelde auteursrecht. Deze uitsluiting van garantie is een essentieel onderdeel van de licentie en een voorwaarde voor de verlening van rechten op het werk. + +8.Uitsluiting van aansprakelijkheid +Behoudens in het geval van een opzettelijke fout of directe schade aan natuurlijke personen, is de licentiegever in geen enkel geval aansprakelijk voor ongeacht welke directe of indirecte, materiële of immateriële schade die voortvloeit uit de licentie of het gebruik van het werk, met inbegrip van, maar niet beperkt tot schade als gevolg van het verlies van goodwill, verloren werkuren, een computerdefect of computerfout, het verlies van gegevens, of enige andere commerciële schade, zelfs indien de licentiegever werd gewezen op de mogelijkheid van dergelijke schade. De licentiegever is echter aansprakelijk op grond van de wetgeving inzake productaansprakelijkheid, voor zover deze wetgeving op het werk van toepassing is. + +9.Aanvullende overeenkomsten +Bij de verspreiding van het werk kunt u ervoor kiezen een aanvullende overeenkomst te sluiten, waarin de verplichtingen of diensten overeenkomstig deze licentie worden omschreven. Indien deze verplichtingen worden aanvaard, kunt u echter alleen in eigen naam en onder eigen verantwoordelijkheid handelen, en dus niet in naam van de oorspronkelijke licentiegever of een bewerker, en kunt u voorts alleen handelen indien u ermee instemt alle bewerkers schadeloos te stellen, te verdedigen of te vrijwaren met betrekking tot de aansprakelijkheid van of vorderingen tegen deze bewerkers op grond van het feit dat u een garantie of aanvullende aansprakelijkheid hebt aanvaard. + +10.Aanvaarding van de licentie +De bepalingen van deze licentie kunnen worden aanvaard door te klikken op het pictogram „Ik ga akkoord”, dat zich bevindt onderaan het venster waarin de tekst van deze licentie is weergegeven, of door overeenkomstig de toepasselijke wetsbepalingen op een soortgelijke wijze met de licentie in te stemmen. Door op dat pictogram te klikken geeft u aan dat u deze licentie en alle voorwaarden ervan ondubbelzinnig en onherroepelijk aanvaardt. Evenzo aanvaardt u onherroepelijk deze licentie en alle voorwaarden ervan door uitoefening van de rechten die u in artikel 2 van deze licentie zijn verleend, zoals het gebruik van het werk, het creëren door u van een bewerking of de verspreiding of mededeling door u van het werk of kopieën ervan. + +11.Voorlichting van het publiek +Indien u het werk verspreidt of mededeelt door middel van elektronische communicatiemiddelen (bijvoorbeeld door voor te stellen het werk op afstand te downloaden), moet het distributiekanaal of het medium (bijvoorbeeld een website) het publiek ten minste de gegevens verschaffen die door het toepasselijke recht zijn voorgeschreven met betrekking tot de licentiegever, de licentie en de wijze waarop deze kan worden geraadpleegd, gesloten, opgeslagen en gereproduceerd door de licentiehouder. + +12.Einde van de licentie +De licentie en de uit hoofde daarvan verleende rechten eindigen automatisch bij elke inbreuk door de licentiehouder op de voorwaarden van de licentie. Dit einde beëindigt niet de licenties van personen die het werk van de licentiehouder krachtens de licentie hebben ontvangen, mits deze personen zich volledig aan de licentie houden. + +13.Overige +Onverminderd artikel 9 vormt de licentie de gehele overeenkomst tussen de partijen met betrekking tot het werk. Indien een bepaling van de licentie volgens het toepasselijke recht ongeldig is of niet uitvoerbaar is, doet dit geen afbreuk aan de geldigheid of uitvoerbaarheid van de licentie in haar geheel. Deze bepaling dient zodanig te worden uitgelegd of gewijzigd dat zij geldig en uitvoerbaar wordt. De Europese Commissie kan, voor zover dit noodzakelijk en redelijk is, versies in andere talen of nieuwe versies van deze licentie of geactualiseerde versies van dit aanhangsel publiceren, zonder de draagwijdte van de uit hoofde van de licentie verleende rechten te beperken. Nieuwe versies van de licentie zullen worden gepubliceerd met een uniek versienummer. Alle door de Europese Commissie goedgekeurde taalversies van deze licentie hebben dezelfde waarde. De partijen kunnen zich beroepen op de taalversie van hun keuze. + +14.Bevoegd gerecht +Onverminderd specifieke overeenkomsten tussen de partijen, +— vallen alle geschillen tussen de instellingen, organen en instanties van de Europese Unie, als licentiegeefster, en een licentiehouder in verband met de uitlegging van deze licentie onder de bevoegdheid van het Hof van Justitie van de Europese Unie, conform artikel 272 van het Verdrag betreffende de werking van de Europese Unie, +— vallen alle geschillen tussen andere partijen in verband met de uitlegging van deze licentie onder de uitsluitende bevoegdheid van het bevoegde gerecht van de plaats waar de licentiegever is gevestigd of zijn voornaamste activiteit uitoefent. + +15.Toepasselijk recht +Onverminderd specifieke overeenkomsten tussen de partijen, +— wordt deze licentie beheerst door het recht van de lidstaat van de Europese Unie waar de licentiegever zijn statutaire zetel, verblijfplaats of hoofdkantoor heeft, +— wordt deze licentie beheerst door het Belgische recht indien de licentiegever geen statutaire zetel, verblijfplaats of hoofdkantoor heeft in een lidstaat van de Europese Unie. + + +Aanhangsel +„Verenigbare licenties” in de zin van artikel 5 EUPL zijn: +— GNU General Public License (GPL) v. 2, v. 3 +— GNU Affero General Public License (AGPL) v. 3 +— Open Software License (OSL) v. 2.1, v. 3.0 +— Eclipse Public License (EPL) v. 1.0 +— CeCILL v. 2.0, v. 2.1 +— Mozilla Public Licence (MPL) v. 2 +— GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +— Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) voor andere werken dan software +— European Union Public Licence (EUPL) v. 1.1, v. 1.2 +— Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) of Strong Reciprocity (LiLiQ-R+). +De Europese Commissie kan dit aanhangsel actualiseren in geval van latere versies van de bovengenoemde licenties zonder dat er een nieuwe EUPL-versie wordt ontwikkeld, zolang die versies de uit hoofde van artikel 2 van deze licentie verleende rechten verlenen en ze de betrokken broncode beschermen tegen exclusieve toe-eigening. +Voor alle andere wijzigingen van of aanvullingen op dit aanhangsel is de ontwikkeling van een nieuwe EUPL-versie vereist. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..088da90 --- /dev/null +++ b/Makefile @@ -0,0 +1,60 @@ +SRCS := \ + CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_adc.c \ + CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c \ + CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_flash.c \ + CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_gpio.c \ + CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwr.c \ + CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_sys.c \ + CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer0.c \ + CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer3.c \ + CH5xx_ble_firmware_library/RVMSIS/core_riscv.c \ + CH5xx_ble_firmware_library/Startup/startup_CH583.S \ + $(wildcard src/*.c) \ + $(wildcard src/*/*.c) + +OUTPUTS = $(patsubst %.S,build/%.o,$(patsubst %.c,build/%.o, $(SRCS))) + +PREFIX ?= riscv-none-embed- +CC = "$(PREFIX)gcc" +OBJCOPY = "$(PREFIX)objcopy" + +CFLAGS += -march=rv32imac -mabi=ilp32 -msmall-data-limit=8 +CFLAGS += -Os +CFLAGS += \ + -ICH5xx_ble_firmware_library/StdPeriphDriver/inc \ + -ICH5xx_ble_firmware_library/RVMSIS \ + -ICH5xx_ble_firmware_library/Core \ + -ICH5xx_ble_firmware_library/BLE + +CFLAGS += -MMD -MP -Wall -fdata-sections -ffunction-sections -Werror=implicit-function-declaration + +LDFLAGS = -march=rv32imac -mabi=ilp32 -msmall-data-limit=8 \ + -lc -lm -lnosys \ + ./CH5xx_ble_firmware_library/StdPeriphDriver/libISP583.a \ + ./CH5xx_ble_firmware_library/BLE/LIBCH58xBLE.a \ + -T CH5xx_ble_firmware_library/Ld/Link.ld -nostartfiles -Xlinker --gc-sections + +all: build/badgewitch.elf build/badgewitch.bin + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) -c $(CFLAGS) $< -o $@ + +build/%.o: %.S + @mkdir -p $(dir $@) + $(CC) -c $(CFLAGS) $< -o $@ + +build/badgewitch.elf: $(OUTPUTS) + @mkdir -pv $(dir $@) + $(CC) $(OUTPUTS) $(LDFLAGS) -o $@ + +build/%.bin: build/%.elf + $(OBJCOPY) -O binary -S $< $@ + +flash: build/badgewitch.bin + wchisp flash build/badgewitch.bin + +clean: + rm -rf build + +-include $(OUTPUTS:%.o=%.d) diff --git a/README.md b/README.md new file mode 100644 index 0000000..a76c23d --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +To use: + +- Download a toolchain (e.g. https://www.mounriver.com/download) +- `make PREFIX=..../bin/riscv-wch-elf-` + +If never flashed before: +- See https://github.com/fossasia/badgemagic-firmware#installation for exact instructions. + +Once loaded, holding down both buttons for a few seconds (or holding down the +lower button whilst waking up the device) should work. + +Shows up as LSLED Badge Witch on bluetooth. +Both HID and CDC-ACM protocol are supported over USB, just as the badge magic firmware supports. + +Code licensed under the EUPL. diff --git a/src/anim.c b/src/anim.c new file mode 100644 index 0000000..e41cefb --- /dev/null +++ b/src/anim.c @@ -0,0 +1,126 @@ +#include +#include +#include "wang.h" +// The left- and rightwards animations work, effectively, the same +// each has a one-screen (44 pixel) dead zone at the start/end + + +// up and down are one-page only + +// fixed just steps through each page +// snowflake idk + +// picture i'm not sure yet but we'll find out +// laser same + +void rotate_vertical(uint16_t *fb, int width, int count) { + for (int i = 0; i < width; i++) { + fb[i] = (fb[i] << count) | (fb[i] >> (11 - count)); + } +} + +void render_moved(uint16_t *fb, int index, int x, int rotate) { + for (int i = 0; i < 44; i++) fb[i] = 0; + + // Read in the initial buffer. + // The image starts at 0, and continues until {width}. + // We trust the wang code not to overread. + if (x < 0) { + if (x < -44) return; + wang_read(index, 0, 44 + x, fb - x); + } else { + wang_read(index, x, 44, fb); + } + if (rotate < 0) rotate = 11 - rotate; + if (rotate > 11) rotate = rotate % 11; + rotate_vertical(fb, 44, rotate); +} + +int apply_modifiers(uint16_t *fb, int frame, int blink, int marquee) { + int can_restart_blink = !blink; + int can_restart_marquee = !marquee; + + if (frame % 6 > 3 && blink) { + for (int i = 0; i < 44; i++) fb[i] = 0; + can_restart_blink = frame % 6 == 5; + } + + if (marquee) { + // marquee pattern is 00010001 + uint16_t marquee = (0x11 << ((frame / 2) % 4)); + // Apply top row + for (int i = 0; i < 44; i++) { + if (marquee & (1 << (i % 8))) fb[i] ^= 1; + } + for (int i = 1; i < 10; i++) { + if (marquee & (1 << ((i - 1) % 8))) fb[43] ^= (1 << i); + } + // The marquee pattern is now shifted by 5 bits. + for (int i = 0; i < 44; i++) { + if (marquee & (1 << ((i + 5) % 8))) fb[43 - i] ^= (1 << 10); + } + for (int i = 1; i < 10; i++) { + if (marquee & (1 << ((i + 4) % 8))) fb[0] ^= (1 << (10 - i)); + } + + can_restart_marquee = frame % 8 == 7; + } + + return can_restart_blink && can_restart_marquee; +} + +int anim_render(uint16_t *fb, int index, int frame) { + int im_width = flash_header.widths[index] * 8; + if (im_width % 44 < 5) { + im_width = im_width - (im_width % 44); + } + + int speed = flash_header.speed_and_mode[index] >> 4; + frame /= 8 - speed; + + int animation = flash_header.speed_and_mode[index] & 0xf; + + int x = 0; + int rotate = 0; + int can_restart_lr = 1; + int can_restart_rotate = 1; + + switch (animation) { + case 0: // left + x = -44 + frame; + can_restart_lr = 0; + if (x >= im_width - 1) can_restart_lr = 1; + break; + case 1: // right + x = im_width + 44 - frame; + can_restart_lr = 0; + if (x < -43) can_restart_lr = 1; + break; + case 2: + rotate = frame % 11; + can_restart_rotate = rotate == 11; + break; + case 3: + rotate = 10 -(frame % 11); + can_restart_rotate = rotate == 0; + break; + case 4: + if (im_width > 44) { + can_restart_lr = 0; + if (frame > (im_width / 44) * 16) { + can_restart_lr = 1; + } + + x = (frame / 16) * 44; + } + + if (im_width - x < 44) { + x -= 22 - (im_width - x) / 2; + } + } + + render_moved(fb, index, x, rotate); + int can_restart_mods = apply_modifiers(fb, frame, flash_header.flash_map & (1 << index), flash_header.marquee_map & (1 << index)); + + return can_restart_lr && can_restart_rotate && can_restart_mods; +} diff --git a/src/ble.c b/src/ble.c new file mode 100644 index 0000000..a6748d9 --- /dev/null +++ b/src/ble.c @@ -0,0 +1,200 @@ +#include +#include + +#include "CH58x_common.h" +#include "CH58x_sys.h" +#include "CH58xBLE_LIB.h" +#include "led.h" +#include "wang.h" + +int ble_on = 0; +int ble_connected = 0; +void ble_toggle(void) { + uint8_t ble_mode = ble_on ? FALSE : TRUE; + GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(ble_mode), &ble_mode); + ble_on = !ble_on; +} + +// We use TMOS only for BLE things and wrap the rest. +static __attribute__((aligned(4), section(".noinit"))) +uint8_t BLE_BUF[1024 * 6]; + +static void ble_calib_cb(void) { + Calibration_LSI(Level_128); +} + +static uint8_t periph_task = INVALID_TASK_ID; + +static uint16_t peripheral_task(uint8_t task_id, uint16_t events) { + if (events & SYS_EVENT_MSG) { + uint8_t *pMsg = tmos_msg_receive(periph_task); + if (pMsg) { + // process the message. noop. + tmos_msg_deallocate(pMsg); + } + + return events ^ SYS_EVENT_MSG; + } + + return 0; +} + +static void gap_onParamUpdate(uint16_t a, uint16_t b, uint16_t c, uint16_t d) { +} +static void gap_onStateChange(gapRole_States_t a, gapRoleEvent_t *b) { +} + +uint8_t advertData[] = { + 0x02, + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + + 0x03, + GAP_ADTYPE_16BIT_MORE, + LO_UINT16(0xFEE0), + HI_UINT16(0xFEE0), +}; + +uint8_t scanRspData[31] = { + 0x05, + GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE, + LO_UINT16(100), + HI_UINT16(100), + LO_UINT16(200), + HI_UINT16(200), + + 0x02, + GAP_ADTYPE_POWER_LEVEL, + 6, + + 19, + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'L', 'S', 'L', 'E', 'D', ' ', 'B', 'a', 'd', 'g', 'e', ' ', 'W', 'i', 't', 'c', 'h', 0, + + 0, 0, 0, 0, +}; + +static gapRolesBroadcasterCBs_t broadcast_handlers = { + 0, + 0, +}; +static gapRolesCBs_t gap_handlers = { + gap_onStateChange, + 0, + gap_onParamUpdate, +}; + +static gapBondCBs_t bond_managers = { + 0, + 0, +}; + +static const uint16_t service_uuid = 0xFEE0; +static const gattAttrType_t service = {2, (uint8_t *) &service_uuid}; + +static const uint16_t rx_char_uuid = 0xFEE1; +static uint8_t rx_char_props = GATT_PROP_WRITE; +static uint8_t rx_char_val[16]; + +static gattAttribute_t attr_table[] = { + {{2, &primaryServiceUUID}, GATT_PERMIT_READ, 0, &service}, + {{2, &characterUUID}, GATT_PERMIT_READ, 0, &rx_char_props}, + {{2, &rx_char_uuid}, GATT_PERMIT_WRITE, 0, &rx_char_val}, +}; + +uint16_t blefb[44] = {0}; + +static bStatus_t write_handler(uint16_t conn_handle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { + if (gattPermitAuthorWrite(pAttr->permissions)) return ATT_ERR_INSUFFICIENT_AUTHOR; + + uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]); + if (uuid != rx_char_uuid) return ATT_ERR_ATTR_NOT_FOUND; + + wang_rx(pValue, len); + + return SUCCESS; +} + +static gattServiceCBs_t service_handlers = { + 0, + write_handler, + 0, +}; + +void ble_init(void) { + bleConfig_t cfg = {0}; + + // BLE heap + cfg.MEMAddr = (uint32_t) BLE_BUF; + cfg.MEMLen = (uint32_t) sizeof(BLE_BUF); + + // not using the bonding information, as we do not support _bonding_. + // This should be changed. but. you know. + + // TODO: magic numbers + // amount of buffered packets + cfg.BufNumber = (512 / 23); + // maximum data length of each packet + cfg.BufMaxLen = (64 + 4); + + cfg.TxNumEvent = 1; + cfg.TxPower = LL_TX_POWEER_6_DBM; + cfg.ConnectNumber = (1 & 3) | (1 << 2); + cfg.SelRTCClock = 1 << 7; + cfg.rcCB = ble_calib_cb; + + uint8_t m[6]; + GetMACAddress(m); + memcpy(cfg.MacAddr, m, 6); + + BLE_LibInit(&cfg); + + sys_safe_access_enable(); + R8_CK32K_CONFIG &= ~(RB_CLK_OSC32K_XT | RB_CLK_XT32K_PON); + sys_safe_access_enable(); + R8_CK32K_CONFIG |= RB_CLK_INT32K_PON; + sys_safe_access_disable(); + + Calibration_LSI(Level_128); + RTC_InitTime(2020, 1, 1, 0, 0, 0); + TMOS_TimerInit(0); + + + periph_task = TMOS_ProcessEventRegister(peripheral_task); + + GAPRole_PeripheralInit(); + + // the GAP parameters all kinda suck to set. sooo + #define SET_PARAM(a, b, c, d) do { static c val = d; a(b, sizeof(val), &val); } while(0) + SET_PARAM(GAPRole_SetParameter, GAPROLE_ADVERT_ENABLED, uint8_t, FALSE); + GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, 31, scanRspData); + GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData); + SET_PARAM(GAPRole_SetParameter, GAPROLE_MIN_CONN_INTERVAL, uint16_t, 6); + SET_PARAM(GAPRole_SetParameter, GAPROLE_MAX_CONN_INTERVAL, uint16_t, 500); + + GGS_SetParameter(GGS_DEVICE_NAME_ATT, 20, "LED Badge Witch\0\0\0\0\0\0\0"); + GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, 100); + GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, 200); + + SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_DEFAULT_PASSCODE, uint32_t, 0); + SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_PAIRING_MODE, uint8_t, GAPBOND_PAIRING_MODE_NO_PAIRING); + SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_MITM_PROTECTION, uint8_t, FALSE); + SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_IO_CAPABILITIES, uint8_t, GAPBOND_IO_CAP_DISPLAY_ONLY); + SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_BONDING_ENABLED, uint8_t, FALSE); + + GAPRole_BroadcasterSetCB(&broadcast_handlers); + + GGS_AddService(GATT_ALL_SERVICES); + GATTServApp_AddService(GATT_ALL_SERVICES); + + GAPRole_PeripheralStartDevice(periph_task, &bond_managers, &gap_handlers); + + GATTServApp_RegisterService(attr_table, GATT_NUM_ATTRS(attr_table), GATT_MAX_ENCRYPT_KEY_SIZE, &service_handlers); +} + +struct connection_data { + uint16_t handle; + uint16_t interval; + uint16_t slave_latency; + uint16_t timeout; +}; diff --git a/src/ble.h b/src/ble.h new file mode 100644 index 0000000..bd7d86c --- /dev/null +++ b/src/ble.h @@ -0,0 +1,7 @@ +#pragma once + +void ble_init(void); +extern int ble_on; +extern int ble_connected; + +void ble_toggle(void); diff --git a/src/button.c b/src/button.c new file mode 100644 index 0000000..587cd81 --- /dev/null +++ b/src/button.c @@ -0,0 +1,79 @@ +#include +#include + +#include "CH58x_common.h" +#include "CH58x_sys.h" +#include "CH58xBLE_LIB.h" + + +volatile int button_count[2] = {15, 0}; +volatile int button_pressed[2] = {1, 0}; + +static void handle_button(int i, int state) { + if (state && button_count[i] < 16) button_count[i]++; + else if (!state && button_count[i] > 0) button_count[i]--; + + if (button_count[i] == 16) button_pressed[i] = 1; + else if (button_count[i] == 0) button_pressed[i] = 0; +} + +__INTERRUPT +__HIGH_CODE +void TMR3_IRQHandler(void) { + handle_button(0, !!GPIOA_ReadPortPin(GPIO_Pin_1)); + handle_button(1, !GPIOB_ReadPortPin(GPIO_Pin_22)); + + TMR3_ClearITFlag(TMR0_3_IT_CYC_END); +} + +void button_init(void) +{ + GPIOA_ModeCfg(GPIO_Pin_1, GPIO_ModeIN_PD); + GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeIN_PU); + + DelayMs(100); + if (!GPIOB_ReadPortPin(GPIO_Pin_22)) { + asm volatile("j 0x00"); + } + + TMR3_TimerInit(FREQ_SYS / 1000); // 1ms timer + TMR3_ITCfg(ENABLE, TMR0_3_IT_CYC_END); + PFIC_EnableIRQ(TMR3_IRQn); + + GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating); + ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0); + ADC_DataCalib_Rough(); + ADC_ChannelCfg(1); + GPIOA_ModeCfg(GPIO_Pin_0, GPIO_ModeIN_PU); + GPIOA_ModeCfg(GPIO_Pin_2, GPIO_ModeIN_PD); +} + +int get_battery_percentage(void) { + uint32_t adc = 0; + + for (int i = 0; i < 24; i++) { + adc += ADC_ExcutSingleConver(); + } + + adc /= 24; + + // We have a rough voltage divider setup + + float v_adc = (adc / 4096.0 * 2.1); + float v_bat = (v_adc / 100.0 * (182.0 + 100.0)); + + if (v_bat < 3.3) + return 0; + + if (v_bat > 4.2) return 100; + + return ((v_bat - 3.3) / (4.2 - 3.3)) * 100; +} + +int is_charging(void) { + return !GPIOA_ReadPortPin(GPIO_Pin_0); +} + +int is_plugged(void) { + return !!GPIOA_ReadPortPin(GPIO_Pin_2); +} diff --git a/src/button.h b/src/button.h new file mode 100644 index 0000000..63a7beb --- /dev/null +++ b/src/button.h @@ -0,0 +1,8 @@ +#pragma once + +void button_init(void); +extern volatile int button_pressed[2]; + +int get_battery_percentage(void); +int is_charging(void); +int is_plugged(void); diff --git a/src/cdc.c b/src/cdc.c new file mode 100644 index 0000000..f164b5b --- /dev/null +++ b/src/cdc.c @@ -0,0 +1,26 @@ +#include +#include + +#include "CH58x_common.h" +#include "CH58x_sys.h" +#include "CH58xBLE_LIB.h" +#include "usb/core.h" +#include "wang.h" + +void cdc_tick(void) { + static uint8_t buf[64]; + static int count = -1; + count = usb_recv(1, buf, 64); + if (count <= 0) return; + + wang_rx(buf, count); +} + +void hid_tick(void) { + static uint8_t buf[64]; + static int count = -1; + count = usb_recv(2, buf, 64); + if (count <= 0) return; + + wang_rx(buf, count); +} diff --git a/src/cdc.h b/src/cdc.h new file mode 100644 index 0000000..d854b28 --- /dev/null +++ b/src/cdc.h @@ -0,0 +1,4 @@ +#pragma once + +void cdc_tick(void); +void hid_tick(void); diff --git a/src/img/menu.xbm b/src/img/menu.xbm new file mode 100644 index 0000000..82a0f09 --- /dev/null +++ b/src/img/menu.xbm @@ -0,0 +1,9 @@ +#define menu_width 44 +#define menu_height 11 +static unsigned char menu_bits[] = { + 0x01, 0x3c, 0x80, 0x07, 0x70, 0x08, 0xfe, 0xdb, 0x7f, 0xfb, 0xaf, 0x07, + 0xfe, 0xdb, 0x7b, 0x7b, 0xaf, 0x07, 0xee, 0xdb, 0x72, 0x5b, 0xad, 0x07, + 0xe6, 0xdb, 0x69, 0x6b, 0xab, 0x07, 0x02, 0xda, 0x73, 0xeb, 0xab, 0x07, + 0xe6, 0xdb, 0x69, 0xeb, 0xab, 0x07, 0xee, 0xdb, 0x72, 0xdb, 0xad, 0x07, + 0xfe, 0xdb, 0x7b, 0x3b, 0xae, 0x07, 0xfe, 0xdb, 0x7f, 0xfb, 0xaf, 0x07, + 0x01, 0x3c, 0x80, 0x07, 0x30, 0x00 }; diff --git a/src/led.c b/src/led.c new file mode 100644 index 0000000..472288b --- /dev/null +++ b/src/led.c @@ -0,0 +1,190 @@ +#include +#include +#include "CH58x_common.h" +#include "CH58x_sys.h" +#include "CH58xBLE_LIB.h" +#include "led.h" + +uint32_t pa_mask; +uint32_t pb_mask; +#define A(v) v +#define B(v) (v | 0x80) +uint8_t pins[23] = { + A(15), + B(18), + B(0), + B(7), + A(12), + A(10), + A(11), + B(9), + B(8), + B(15), + B(14), + B(13), + B(12), + B(5), + A(4), + B(3), + B(4), + B(2), + B(1), + B(6), + B(21), + B(20), + B(19), +}; + +// Set up the pa_mask and pb_mask values. +// These are used to mask out the GPIOs we control from those we do not. +void display_init(void) { + for (int i = 0; i < 23; i++) { + if (pins[i] & 0x80) { + pb_mask |= (1 << (pins[i] & 0x7F)); + } else { + pa_mask |= (1 << (pins[i] & 0x7F)); + } + } +} + +// Commit a struct row_buf to the display. +__HIGH_CODE +void display_commit(struct row_buf *b) { + // To avoid as much artifacting, we first tri-state all our pins. + // This is done in order of PD_DRV (which controls either the pull-down + // or the current drive capability). + R32_PA_PD_DRV = (R32_PA_PD_DRV & ~pa_mask); + R32_PB_PD_DRV = (R32_PB_PD_DRV & ~pb_mask); + + // We then disable drive any of the previously-output GPIOs low. + R32_PA_OUT = (R32_PA_OUT & ~pa_mask); + R32_PB_OUT = (R32_PB_OUT & ~pb_mask); + + // Now we set all GPIOs as inputs, tristating them. + R32_PA_DIR = (R32_PA_DIR & ~pa_mask); + R32_PB_DIR = (R32_PB_DIR & ~pb_mask); + + // We set the nicessary pins to output (driving them low), + R32_PA_DIR |= b->pa_dir; + // Configure the current drive (which is a noop, as none of the pins should be driven high).. + R32_PA_PD_DRV |= b->pa_drv; + + // (Do the same on GPIO bank B) + R32_PB_DIR |= b->pb_dir; + R32_PB_PD_DRV |= b->pb_drv; + + // And drive the one pin high, setting up the entire matrix. + R32_PA_OUT |= b->pa_out; + R32_PB_OUT |= b->pb_out; + + // This is most plausibly overkill, and needs some testing. +} + +void display_make_buf(uint16_t *fb, struct row_buf *b, int i) { + #define SET_OUT(pin) if (pin & 0x80) { b->pb_dir |= (1 << (pin & 0x7F)); } else { b->pa_dir |= (1 << pin); } + #define SET_HI(pin) if (pin & 0x80) { b->pb_out |= (1 << (pin & 0x7F)); } else { b->pa_out |= (1 << pin); } + + b->pa_dir = 0; + b->pa_out = 0; + b->pa_drv = 0; + b->pb_dir = 0; + b->pb_out = 0; + b->pb_drv = 0; + + uint16_t col1 = fb[i * 2]; + uint16_t col2 = fb[i * 2 + 1]; + + // On the first column, the lower two pins are swapped. Fix this in software. + if (i == 0) { + uint16_t bit = col1 & 1; + col1 = (col1 & 0xFFFE) | (col2 & 1); + col2 = (col2 & 0xFFFE) | bit; + } + + // The LEDs are written in a zig-zag pattern. + uint32_t merged = 0; + merged |= ((col1 & 1) << 22); + merged |= ((col2 & 1) << 23); + for (int j = 0; j < 11; j++) { + col1 >>= 1; + col2 >>= 1; + + merged >>= 2; + merged |= (col1 & 1) << 22; + merged |= (col2 & 1) << 23; + } + + // In this LED matrix, we set row N as a high output, + // then set all other lines to tristate or low, depending + // on whether they should be on or off. + int count = 0; + for (int j = 0; j < 23; j++) { + if (j == i) continue; + + if (merged & 1) { + count++; + SET_OUT(pins[j]); + } + merged >>= 1; + } + + // Set the charlieplexed row. + // This avoids setting it if the row is empty, + // to decrease artifacting. + if (count) { + SET_OUT(pins[i]); SET_HI(pins[i]); + } + + // If we have >5 LEDs on, enable the 20mA drive mode. + if (count > 5) { + b->pa_drv = b->pa_dir; + b->pb_drv = b->pb_dir; + } +} + +void display_make_buf_all(uint16_t *fb, struct row_buf *b) { + for (int i = 0; i < 22; i++) { + display_make_buf(fb, b + i, i); + } +} + +int display_brightness = 0; +static struct row_buf display_screens[22 * 2]; +static struct row_buf blank = {0}; + +struct row_buf *display_screen = display_screens; +static struct row_buf *display_screen_render = display_screens + 22; + +void display_flip(void) { + struct row_buf *new_render = display_screen == display_screens ? (display_screens + 22) : display_screens; + struct row_buf *old_render = display_screen; + + __atomic_exchange(&display_screen, &display_screen_render, &display_screen_render, __ATOMIC_RELAXED); +} + +__INTERRUPT +__HIGH_CODE +void TMR0_IRQHandler(void) +{ + static int cur_index; + static int cur_bness; + + // If this is a spurious interrupt, skip it. + if (!TMR0_GetITFlag(TMR0_3_IT_CYC_END)) return; + TMR0_ClearITFlag(TMR0_3_IT_CYC_END); + + cur_index += 1; + if (cur_index > 21) { + cur_index = 0; + cur_bness++; + if (cur_bness == 16) { + cur_bness = 0; + } + } + + if (cur_bness > display_brightness) { + display_commit(&blank); + } else { + display_commit(display_screen_render + cur_index); + } +} diff --git a/src/led.h b/src/led.h new file mode 100644 index 0000000..298d8ca --- /dev/null +++ b/src/led.h @@ -0,0 +1,24 @@ +#pragma once + +extern uint32_t pa_mask; +extern uint32_t pb_mask; + +struct row_buf { + uint32_t pa_dir; + uint32_t pa_out; + uint32_t pa_drv; + uint32_t pb_dir; + uint32_t pb_out; + uint32_t pb_drv; +}; + + +void display_commit(struct row_buf *b); +void display_make_buf(uint16_t *fb, struct row_buf *b, int i); +void display_make_buf_all(uint16_t *fb, struct row_buf *b); + +extern int display_brightness; +extern struct row_buf *display_screen; + +void display_flip(void); +void display_init(void); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..49f9b8d --- /dev/null +++ b/src/main.c @@ -0,0 +1,136 @@ +#include +#include + +#include "CH58x_common.h" +#include "CH58x_sys.h" +#include "CH58xBLE_LIB.h" +#include "usb/core.h" +#include "led.h" +#include "button.h" +#include "menu.h" +#include "ble.h" +#include "cdc.h" +#include "wang.h" + +int anim_render(uint16_t *fb, int index, int frame); + +enum usb_control_resp bl_handler(enum usb_control_state state) { + if (usb_control_request.bmRequestType != 0x60) return USB_CONTROL_RESP_PASS; + + if (usb_control_request.bRequest != 0x69) + return USB_CONTROL_RESP_STALL; + + asm volatile("j 0x00"); + return USB_CONTROL_RESP_ACK; +} + + +int btn1_was_pressed = 1; +int btn2_was_pressed = 0; +int btn1_hold = 0; +int btn2_hold = 0; + +int image_index = 0; + +int frame = 0; +int subframe = 0; + +int main_handler(void) { + + #define TIMER(btn0, btn1, v, count) if (button_pressed[0] != btn0 || button_pressed[1] != btn1) { v = 0; } else if (v < count) { v += 1; } else + static int menu_timer = 0; + TIMER(1, 0, menu_timer, 500) { + display_brightness = (display_brightness + 15) % 16; + menu_timer = 0; + menu_switch(); + return 1; + } + + if (button_pressed[0] && !btn1_was_pressed) { + display_brightness = (display_brightness + 1) % 16; + } + + if (button_pressed[1] && !btn2_was_pressed) { + if (flash_header_valid) { + image_index++; + if (!flash_header.widths[image_index]) image_index = 0; + frame = 0; + subframe = 99999; + } + display_flip(); + } + + subframe++; + if (subframe > 32 && flash_header_valid) { + // approximately 60fps + subframe = 0; + + uint16_t fb[44]; + if (anim_render(fb, image_index, frame)) { + frame = 0; + } else { + frame++; + } + display_make_buf_all(fb, display_screen); + display_flip(); + } + + btn2_was_pressed = button_pressed[1]; + btn1_was_pressed = button_pressed[0]; + + return 0; +} + +int main() +{ + SetSysClock(CLK_SOURCE_PLL_60MHz); + + button_init(); + + display_init(); + + WWDG_SetCounter(0x7F); + WWDG_ResetCfg(ENABLE); + + TMR0_TimerInit((FREQ_SYS / 16000) / 2); + TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END); + PFIC_EnableIRQ(TMR0_IRQn); + + TMR3_TimerInit(FREQ_SYS / 200); + TMR3_ITCfg(ENABLE, TMR0_3_IT_CYC_END); + PFIC_EnableIRQ(TMR3_IRQn); + + usb_register_handler(bl_handler); + usb_init(); + + ble_init(); + + wang_init(); + + while (1) { + WWDG_SetCounter(0x7F); + static int btldr_timer = 0; + if (button_pressed[1] && button_pressed[0]) { + btldr_timer++; + if (btldr_timer > 1000) asm volatile("j 0x00"); + } else { + btldr_timer = 0; + } + + static int cur_handler = 0; + if (cur_handler) { + cur_handler = menu_handler(); + if (!cur_handler) { + btn2_was_pressed = button_pressed[1]; + btn1_was_pressed = button_pressed[0]; + subframe = 99999; + } + } else + cur_handler = main_handler(); + + TMOS_SystemProcess(); + cdc_tick(); + hid_tick(); + DelayMs(1); + } +} diff --git a/src/menu.c b/src/menu.c new file mode 100644 index 0000000..44e57bd --- /dev/null +++ b/src/menu.c @@ -0,0 +1,145 @@ +#include +#include + +#include "CH58x_common.h" +#include "CH58x_sys.h" +#include "CH58xBLE_LIB.h" +#include "usb/core.h" +#include "led.h" +#include "ble.h" +#include "button.h" + +#include "img/menu.xbm" + +static void boop() +{ + WWDG_ResetCfg(DISABLE); + PFIC_DisableIRQ(TMR0_IRQn); + PFIC_DisableIRQ(TMR3_IRQn); + + // Stop wasting energy + GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_Floating); + GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_Floating); + + GPIOA_ModeCfg(GPIO_Pin_1, GPIO_ModeIN_PD); + while (GPIOA_ReadPortPin(GPIO_Pin_1)) DelayMs(1); + + DelayMs(100); + // 0 to 1 (pulldown, so implies being _pressed_) + // however, this doesn't work? + GPIOA_ITModeCfg(GPIO_Pin_1, GPIO_ITMode_HighLevel); + PFIC_EnableIRQ(GPIO_A_IRQn); + // Wait for shit to settle + while (GPIOA_ReadPortPin(GPIO_Pin_1)) DelayMs(1); + PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay); + + /* Good bye */ + LowPower_Shutdown(0); +} + +static void render_xbm(unsigned char *bits, struct row_buf *b) { + uint16_t fb[45] = {0}; + int index = 0; + for (int j = 0; j < 11; j++) { + index = j * 48; + for (int i = 0; i < 44; i++) { + int bit = bits[index / 8] & (1 << (index % 8)); + if (!bit) fb[i] |= (1 << j); + index++; + } + } + + display_make_buf_all(fb, b); +} + +int menu_index = 0; + +static int btn0_pressed = 0; +static int btn1_pressed = 0; + +void menu_render(void) { + char buffer[(48 * 11) / 8]; + memcpy(buffer, menu_bits, sizeof(buffer)); + int invert_index = 1 + menu_index * 13; + for (int i = invert_index; i < (invert_index + 9); i++) { + for (int j = 1; j < 10; j++) + buffer[(i / 8) + (j * 48 / 8)] ^= (1 << (i % 8)); + } + + int batt_percent = ((get_battery_percentage() + 7) * 10) / 100; + int charge = is_charging() || is_plugged(); + for (int i = 39; i < 43; i++) { + for (int j = 0; j < 10; j++) { + int index = 10 - j; + if (j <= batt_percent) { + buffer[(i / 8) + (index * 48 / 8)] &= ~(1 << (i % 8)); + } else if (charge && (j - 2) <= batt_percent) { + if (i % 2 == j % 2) + buffer[(i / 8) + (index * 48 / 8)] &= ~(1 << (i % 8)); + } + } + } + + if (!ble_on) { + #define PIX(x, y) buffer[((x) / 8) + ((y) * 48 / 8)] |= (1 << ((x) % 8)) + for (int i = 0; i < 11; i += 2) { + PIX(13 + i, 0); + PIX(13 + i, 10); + PIX(13, i); + PIX(23, i); + } + } + + render_xbm(buffer, display_screen); + display_flip(); +} + +void menu_switch(void) { + btn0_pressed = button_pressed[0]; + btn1_pressed = button_pressed[1]; + menu_index = 0; + + menu_render(); +} + +int menu_handler(void) { + static int btldr_timer = 0; + static int render_ticks = 0; + render_ticks++; + + if (button_pressed[1] && button_pressed[0]) { + btldr_timer++; + if (btldr_timer > 2000) asm volatile("j 0x00"); + } else { + btldr_timer = 0; + } + + if (button_pressed[0] && !btn0_pressed && !button_pressed[1]) { + menu_index = (menu_index + 1) % 3; + menu_render(); + render_ticks = 0; + } + + if (button_pressed[1] && !btn1_pressed && !button_pressed[0]) { + if (menu_index == 0) { + return 0; + } else if (menu_index == 1) { + ble_toggle(); + menu_render(); + render_ticks = 0; + } else if (menu_index == 2) { + boop(); + } + } + + if (render_ticks > 125) { + render_ticks = 0; + menu_render(); + } + + btn0_pressed = button_pressed[0]; + btn1_pressed = button_pressed[1]; + + return 1; +} + diff --git a/src/menu.h b/src/menu.h new file mode 100644 index 0000000..57f21ae --- /dev/null +++ b/src/menu.h @@ -0,0 +1,4 @@ +#pragma once + +void menu_switch(void); +int menu_handler(void); diff --git a/src/usb/core.c b/src/usb/core.c new file mode 100644 index 0000000..2ca6fe1 --- /dev/null +++ b/src/usb/core.c @@ -0,0 +1,232 @@ +#include +#include "core.h" +#include "CH58x_common.h" + +static volatile uint8_t *ep_t_len_regs[] = { + &R8_UEP0_T_LEN, + &R8_UEP1_T_LEN, + &R8_UEP2_T_LEN, + &R8_UEP3_T_LEN, + &R8_UEP4_T_LEN, + &R8_UEP5_T_LEN, + &R8_UEP6_T_LEN, + &R8_UEP7_T_LEN, +}; + +static volatile uint8_t *ep_ctrl_regs[] = { + &R8_UEP0_CTRL, + &R8_UEP1_CTRL, + &R8_UEP2_CTRL, + &R8_UEP3_CTRL, + &R8_UEP4_CTRL, + &R8_UEP5_CTRL, + &R8_UEP6_CTRL, + &R8_UEP7_CTRL, +}; + +static uint8_t recvlens[8]; +uint8_t bConfigurationValue = 0; + +// The hardware requires EP0 and EP4 to share a contiguous DMA buffer. +// Fuck if I know why. +__attribute__((aligned(4))) volatile uint8_t ep04_buf[64 + 64 + 64]; + +__attribute__((aligned(4))) volatile uint8_t epbuf[(8 - 2) * 2 * 64]; + +volatile uint8_t *buf_for_ep(uint8_t ep, int dir_in) { + if (ep == 0) return ep04_buf; + if (ep == 4) return ep04_buf + (dir_in ? 128 : 64); + + // EP0 and EP4 aren't in here. so skip them. + ep -= 1; + if (ep > 3) ep -= 1; + return epbuf + (ep * 128 + (dir_in ? 64 : 0)); +} + +// Configure the response to set for the next token for the endpoint. +// The interrupt handler will reconfigure this to return NAK whenever +// the next token has been received. +enum usb_endpoint_state set_endpoint_state(uint8_t endpoint, enum usb_endpoint_state state) { + int dir_in = endpoint & 0x80; // 0 -> OUT endpoint, 1 -> IN endpoint + int ep_num = endpoint & 0x7F; + + if (dir_in) { + uint8_t prev_state = *ep_ctrl_regs[ep_num] & MASK_UEP_T_RES; + *ep_ctrl_regs[ep_num] = (*ep_ctrl_regs[ep_num] & ~MASK_UEP_T_RES) | (state & 0x03); + return prev_state; + } else { + uint8_t prev_state = (*ep_ctrl_regs[ep_num] & MASK_UEP_R_RES) >> 2; + *ep_ctrl_regs[ep_num] = (*ep_ctrl_regs[ep_num] & ~MASK_UEP_R_RES) | ((state & 0x03) << 2); + return prev_state; + } +} + + +// Toggle the DATA0/DATA1 toggle bit, indicating which of +// DATA0 and DATA1 to use fo rthe next receiving or sending of data. +// These bits are only toggled once data has been successfully transferred; +// a la USB_EP_STATE_ACK. +// +// The SETUP control transfers on endoint 0 _always_ use DATA0. +static void flip_endpoint_data_toggle(uint8_t endpoint) { + int dir_in = endpoint & 0x80; + int ep_num = endpoint & 0x7F; + + if (dir_in) { + *ep_ctrl_regs[ep_num] ^= RB_UEP_T_TOG; + } else { + *ep_ctrl_regs[ep_num] ^= RB_UEP_R_TOG; + } +} + +static void handle_bus_reset() { + R8_USB_INT_FG = RB_UIF_BUS_RST; + R8_USB_DEV_AD = 0; + bConfigurationValue = 0; +} + +static void handle_suspend() { + R8_USB_INT_FG = RB_UIF_SUSPEND; + + // TODO +} + +static void handle_sof() { + R8_USB_INT_FG = RB_UIF_HST_SOF; +} + + +__HIGH_CODE +static void handle_transfer(uint8_t ep_num, int is_in) { + uint8_t endpoint = ep_num | (is_in ? 0x80 : 0); + + // We may have received a transfer. + // If we expected this transfer, toggle the DATA0/DATA1 bits. + enum usb_endpoint_state prev_state = set_endpoint_state(endpoint, USB_EP_STATE_NAK); + if (prev_state == USB_EP_STATE_ACK) { + flip_endpoint_data_toggle(endpoint); + } + + if (ep_num == 0) { + handle_ctrl_transfer(is_in); + return; + } + + if (!is_in) { + recvlens[endpoint] = R8_USB_RX_LEN; + } +} + +void usb_init() { + + R8_USB_CTRL = 0x00; + + R8_UEP4_1_MOD = RB_UEP4_RX_EN | RB_UEP4_TX_EN | + RB_UEP1_RX_EN | RB_UEP1_TX_EN; + R8_UEP2_3_MOD = RB_UEP2_RX_EN | RB_UEP2_TX_EN | + RB_UEP3_RX_EN | RB_UEP3_TX_EN; + R8_UEP567_MOD = RB_UEP7_RX_EN | RB_UEP7_TX_EN | + RB_UEP6_RX_EN | RB_UEP6_TX_EN | + RB_UEP5_RX_EN | RB_UEP5_TX_EN; + + R16_PIN_ANALOG_IE |= RB_PIN_USB_IE | RB_PIN_USB_DP_PU; + R8_UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; + + R8_USB_DEV_AD = 0x00; + R8_USB_INT_FG = 0xFF; + + R16_UEP0_DMA = ep04_buf; + R16_UEP1_DMA = epbuf + 0 * 128; + R16_UEP2_DMA = epbuf + 1 * 128; + R16_UEP3_DMA = epbuf + 2 * 128; + R16_UEP5_DMA = epbuf + 3 * 128; + R16_UEP6_DMA = epbuf + 4 * 128; + R16_UEP7_DMA = epbuf + 5 * 128; + + for (int i = 0; i < 8; i++) { + set_endpoint_state(i, USB_EP_STATE_NAK); + set_endpoint_state(i | 0x80, USB_EP_STATE_NAK); + } + + R8_USB_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN; + R8_USB_INT_EN = RB_UIE_SUSPEND | RB_UIE_BUS_RST | RB_UIE_TRANSFER; + + PFIC_EnableIRQ(USB_IRQn); +} + +__INTERRUPT +__HIGH_CODE +void USB_IRQHandler(void) { + uint8_t interrupt = R8_USB_INT_FG; + + if (interrupt & RB_UIF_BUS_RST) { + handle_bus_reset(); + } + + if (interrupt & RB_UIF_SUSPEND) { + handle_suspend(); + } + + if (interrupt & RB_UIF_TRANSFER) { + uint8_t status = R8_USB_INT_ST; + uint8_t ep_num = status & MASK_UIS_ENDP; + uint8_t token = ((status & MASK_UIS_TOKEN) >> 4) & 0x03; + + if (token == 0x00) { // OUT + if (status & RB_UIS_TOG_OK) handle_transfer(ep_num, 0); + R8_USB_INT_FG = RB_UIF_TRANSFER; + } else if (token == 0x01) { // SOF + handle_sof(); + R8_USB_INT_FG = RB_UIF_TRANSFER; + } else if (token == 0x02) { // IN + handle_transfer(ep_num, 1); + R8_USB_INT_FG = RB_UIF_TRANSFER; + } + if ((status & RB_UIS_SETUP_ACT)) { + handle_setup_request(); + R8_USB_INT_FG = RB_UIF_TRANSFER; + } + } +} + +// Receive up to buflen bytes from selected OUT endpoint. +// If data is not yet available, returns -1. +int16_t usb_recv(uint8_t endpoint, void *buffer, size_t buflen) { + if (recvlens[endpoint] == 0xFF) { + set_endpoint_state(endpoint, USB_EP_STATE_ACK); + return -1; + } + + if (recvlens[endpoint] < buflen) { + buflen = recvlens[endpoint]; + } + + recvlens[endpoint] = 0xFF; + + memcpy(buffer, buf_for_ep(endpoint, 0), buflen); + return buflen; +} + +// Sends up to buflen bytes to selected IN endpoint. +// If the buffer is still busy, returns -1. +int16_t usb_xmit(uint8_t endpoint, void *buffer, size_t buflen) { + if ((*ep_ctrl_regs[endpoint] & MASK_UEP_T_RES) != USB_EP_STATE_NAK) { + return -1; + } + + if (buflen > 64) buflen = 64; + + memcpy(buf_for_ep(endpoint, 1), buffer, buflen); + *ep_t_len_regs[endpoint] = buflen; + set_endpoint_state(endpoint | 0x80, USB_EP_STATE_ACK); + + return buflen; +} + +int usb_can_xmit(uint8_t endpoint) { + return (*ep_ctrl_regs[endpoint] & MASK_UEP_T_RES) == USB_EP_STATE_NAK; +} + +int usb_connected(void) { + return !!(R8_USB_MIS_ST & RB_UMS_SUSPEND); +} diff --git a/src/usb/core.h b/src/usb/core.h new file mode 100644 index 0000000..9cd761b --- /dev/null +++ b/src/usb/core.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include + +enum usb_endpoint_state { + USB_EP_STATE_ACK = 0, + USB_EP_STATE_TIMEOUT = 1, + USB_EP_STATE_NAK = 2, + USB_EP_STATE_STALL = 3, +}; + +struct __attribute__((packed)) usb_control_request { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +}; + +extern struct usb_control_request usb_control_request; +extern void *control_transfer_buf; +extern uint16_t control_transfer_len; +extern uint8_t bConfigurationValue; + +extern volatile uint8_t ep04_buf[64 + 64 + 64]; +extern volatile uint8_t epbuf[(8 - 2) * 2 * 64]; + +enum usb_control_resp { + USB_CONTROL_RESP_PASS, + USB_CONTROL_RESP_ACK, + USB_CONTROL_RESP_STALL, +}; + +enum usb_control_state { + USB_CONTROL_SETUP, + USB_CONTROL_DATA_SENT, + USB_CONTROL_FINISHED, +}; + +typedef enum usb_control_resp (*usb_control_request_handler)(enum usb_control_state); +void usb_register_handler(usb_control_request_handler); + +enum usb_control_request_type { + USB_CONTROL_REQUEST_TYPE_OUT, + USB_CONTROL_REQUEST_TYPE_IN, + USB_CONTROL_REQUEST_TYPE_NO_DATA, +}; + +void ctrl_respond_out(void *buf, uint16_t len); +void handle_ctrl_transfer(int is_in); + +int16_t usb_recv(uint8_t endpoint, void *buffer, size_t buflen); +int16_t usb_xmit(uint8_t endpoint, void *buffer, size_t buflen); +int usb_can_xmit(uint8_t ep); + +void usb_init(); +void handle_setup_request(); +enum usb_endpoint_state set_endpoint_state(uint8_t endpoint, enum usb_endpoint_state state); + +int usb_connected(void); diff --git a/src/usb/ctrl.c b/src/usb/ctrl.c new file mode 100644 index 0000000..cb69ea5 --- /dev/null +++ b/src/usb/ctrl.c @@ -0,0 +1,362 @@ +#include +#include "core.h" +#include "CH58x_common.h" + +struct usb_control_request usb_control_request; + +// These track the currently ongoing control transfer. +void *control_transfer_buf; +uint16_t control_transfer_len; + +void ctrl_respond_out(void *buf, uint16_t len) { + control_transfer_buf = buf; + if (len > usb_control_request.wLength) len = usb_control_request.wLength; + control_transfer_len = len; +} + +__HIGH_CODE +static enum usb_control_request_type ctrlreq_type() { + if (!usb_control_request.wLength) { + return USB_CONTROL_REQUEST_TYPE_NO_DATA; + } + + return usb_control_request.bmRequestType & 0x80 ? USB_CONTROL_REQUEST_TYPE_IN : USB_CONTROL_REQUEST_TYPE_OUT; +} + +uint8_t device_descriptor[18] = { + 0x12, + 0x01, + 0x00, 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x16, 0x04, + 0x20, 0x50, + 0x20, 0x04, + 0x00, + 0x00, + 0x00, + 0x01, +}; + +uint8_t config_descriptor[0x6b] = { + 0x09, // bLength + 0x02, // bDescriptorType + 0x6b, 0x00, // wTotalLength + 0x03, // bNumInterfaces + 0x01, // bConfigurationValue + 0x00, // iConfiguration + 0x80, // bmAttributes + 0x64, // bMaxPower + + 0x09, // bLength + 0x04, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints + 0x03, // bInterfaceClass (HID) + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0x00, // iInterface + + // HID descriptor + 0x09, + 0x21, + 0x11, 0x01, + 0x00, + 0x01, + 0x22, + 0x18, 0x00, + + 0x07, + 0x05, + 0x82, + 0x03, + 0x10, 0x00, + 0x01, + + 0x07, + 0x05, + 0x02, + 0x03, + 0x10, 0x00, + 0x01, + + + 0x08, // bLength + 0x0b, // bDescriptorType ~ INTERFACE ASSOCIATION DESCRIPTOR + 0x01, // bFirstInterface + 0x02, // bInterfaceCount + 0x02, // bFunctionClass 0x02 + 0x02, // bFunctionSubclass 0x02 + 0x01, // bFunctionProtocol 0x01 + 0x00, // iFunction + + 0x09, // bLength + 0x04, // bDescriptorType + 0x01, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints + 0x02, // bInterfaceClass + 0x02, // bInterfaceSubClass + 0x01, // bInterfaceProtocol + 0x00, // iInterface + + 0x05, // bLength + 0x24, // bDescriptorType + 0x00, // bDescriptorSubtype + 0x10, 0x01, // bcdCDC + + 0x05, // bLength + 0x24, // bDescriptorType + 0x01, // bDescriptorSubtype + 0x00, // bmCapabilities + 0x01, // bDataInterface + + // ACM descripotor + 0x04, // bLength + 0x24, // bDescriptorType + 0x02, // bDescriptorSubtype + 0x00, // bmCapabilities + + // ACM union descriptor + 0x05, // bLength + 0x24, // bDescriptorType + 0x06, // bDescriptorSubtype + 0x00, // bMasterInterface + 0x01, // bSlaveInterface0 + + 0x07, // bLength + 0x05, // bDescriptorType + 0x88, // bEndpointAddress + 0x03, // bmAttributes + 0x10, 0x00, // wMaxPacketSize + 0x01, // bInterval + + 0x09, // bLength + 0x04, // bDescriptorType + 0x02, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints + 0x0a, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0x00, // iInterface + + 0x07, // bLength + 0x05, // bDescriptorType + 0x81, // bEndpointAddress + 0x02, // bmAttributes + 0x20, 0x00, // wMaxPacketSize + 0x01, // bInterval + + 0x07, // bLength + 0x05, // bDescriptorType + 0x01, // bEndpointAddress + 0x02, // bmAttributes + 0x20, 0x00, // wMaxPacketSize + 0x01, // bInterval +}; + +uint8_t report_descriptor[24] = { + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x01, // Usage (0x01) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x02, // Usage (0x02) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0xFF, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x40, // Report Count (64) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x03, // Usage (0x03) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0xC0 // End Collection +}; + +__HIGH_CODE +static enum usb_control_resp handle_hid_request(enum usb_control_state state) { + if ((usb_control_request.bmRequestType & 0x7F) != 0x21 && (usb_control_request.bmRequestType & 0x7f) != 1) return USB_CONTROL_RESP_PASS; + if (usb_control_request.wIndex != 0) return USB_CONTROL_RESP_PASS; + + if (usb_control_request.bmRequestType == 0x81 && usb_control_request.bRequest == 0x06 && usb_control_request.wValue == 0x2200) { + if (state == USB_CONTROL_SETUP) ctrl_respond_out(report_descriptor, 24); + return USB_CONTROL_RESP_ACK; + } + + return USB_CONTROL_RESP_STALL; +} + +__HIGH_CODE +static enum usb_control_resp handle_main_request(enum usb_control_state state) { + if (usb_control_request.bmRequestType & 0x7F != 0x00) return USB_CONTROL_RESP_PASS; + + switch (usb_control_request.bRequest) { + case 0: // GET_STATUS + if (state == USB_CONTROL_SETUP) { + static uint16_t status_val = 0; + ctrl_respond_out((void *)&status_val, 2); + } + + return USB_CONTROL_RESP_ACK; + case 1: // CLEAR_FEATURE + case 3: // SET_FEATURE + return USB_CONTROL_RESP_STALL; + case 5: // SET_ADDRESS + if (state == USB_CONTROL_FINISHED) { + R8_USB_DEV_AD = (uint8_t) usb_control_request.wValue; + } + + return USB_CONTROL_RESP_ACK; + case 6: // GET_DESCRIPTOR + if ((usb_control_request.wValue & 0xFF00) == 0x0100) { + if (state == USB_CONTROL_SETUP) ctrl_respond_out(device_descriptor, sizeof(device_descriptor)); + } else if ((usb_control_request.wValue & 0xFF00) == 0x0200) { + if (state == USB_CONTROL_SETUP) ctrl_respond_out(config_descriptor, sizeof(config_descriptor)); + } else { + return USB_CONTROL_RESP_STALL; + } + + return USB_CONTROL_RESP_ACK; + case 7: // SET_DESCRIPTOR + return USB_CONTROL_RESP_STALL; + case 8: // GET_CONFIGURATION + if (state == USB_CONTROL_SETUP) { + ctrl_respond_out(&bConfigurationValue, 1); + } + + return USB_CONTROL_RESP_STALL; + case 9: // SET_CONFIGURATION + if (usb_control_request.wValue > 1 || usb_control_request.wLength || usb_control_request.wIndex) { + return USB_CONTROL_RESP_STALL; + } + + return USB_CONTROL_RESP_ACK; + + case 10: // GET_INTERFACE + case 11: // SET_INTERFACE + case 12: // SYNCH_FRAME + return USB_CONTROL_RESP_STALL; + } + + return USB_CONTROL_RESP_STALL; +} + +static usb_control_request_handler handlers[16] = {0}; +static int handlers_index = 0; + +void usb_register_handler(usb_control_request_handler handler) { + handlers[handlers_index++] = handler; +} + +__HIGH_CODE +static enum usb_control_resp call_handler(enum usb_control_state state) { + enum usb_control_resp r = handle_main_request(state); + if (r != USB_CONTROL_RESP_PASS) return r; + + r = handle_hid_request(state); + if (r != USB_CONTROL_RESP_PASS) return r; + + for (int i = 0; i < handlers_index; i++) { + if (!handlers[i]) continue; + enum usb_control_resp resp = handlers[i](state); + if (resp != USB_CONTROL_RESP_PASS) return resp; + } + + return USB_CONTROL_RESP_STALL; +} + +__HIGH_CODE +void handle_ctrl_transfer(int is_in) { + if (!control_transfer_buf) { + call_handler(USB_CONTROL_FINISHED); + if (is_in) { + R8_UEP0_CTRL = RB_UEP_T_TOG | RB_UEP_R_TOG | UEP_R_RES_ACK | UEP_T_RES_STALL; + return; + } + R8_UEP0_CTRL = RB_UEP_T_TOG | RB_UEP_R_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL; + return; + } + + + if (is_in) { + // Account for the bytes having been sent. + if (control_transfer_len >= 64) { + control_transfer_len -= 64; + control_transfer_buf += 64; + } else + control_transfer_len = 0; + + // If we have more data to transfer, set up the next + // DMA. + + if (control_transfer_len > 0) { + memcpy(ep04_buf, control_transfer_buf, control_transfer_len > 64 ? 64 : control_transfer_len); + R8_UEP0_T_LEN = control_transfer_len > 64 ? 64 : control_transfer_len; + set_endpoint_state(0x80, USB_EP_STATE_ACK); + } else { + enum usb_control_resp result = call_handler(USB_CONTROL_DATA_SENT); + control_transfer_buf = 0; + set_endpoint_state(0x00, result == USB_CONTROL_RESP_ACK ? USB_EP_STATE_ACK : USB_EP_STATE_STALL); + } + } else { + uint8_t ack_bytes = R8_USB_RX_LEN; + if (ack_bytes > control_transfer_len) { + ack_bytes = control_transfer_len; + } + + control_transfer_len -= ack_bytes; + memcpy(control_transfer_buf, ep04_buf, ack_bytes); + control_transfer_buf += ack_bytes; + + if (control_transfer_len > 0) { + // We have more data to receive. so re-ready the endpoint. + set_endpoint_state(0x00, USB_EP_STATE_ACK); + } else { + enum usb_control_resp result = call_handler(USB_CONTROL_DATA_SENT); + control_transfer_buf = 0; + set_endpoint_state(0x80, result == USB_CONTROL_RESP_ACK ? USB_EP_STATE_ACK : USB_EP_STATE_STALL); + } + } +} + +__HIGH_CODE +void handle_setup_request() { + // Copy the setup request from the EP0 buffer. + memcpy(&usb_control_request, ep04_buf, 8); + + // We don't expect the previous request to be driven anymore. + // Reset the control transfer. + control_transfer_buf = 0; + control_transfer_len = 0; + + // The next requests (and responses) will start with DATA1. + R8_UEP0_CTRL = RB_UEP_T_TOG | RB_UEP_R_TOG | UEP_R_RES_NAK | UEP_T_RES_NAK; + + if (call_handler(USB_CONTROL_SETUP) != USB_CONTROL_RESP_ACK) { + control_transfer_buf = 0; + control_transfer_len = 0; + + // We need to stall this request. + // This is done by stalling either the first data stage packet, + // or the status stage packet. + + // In an OUT type control request, the next request will be an OUT. + // In other cases, it will always be IN. + if (ctrlreq_type() != USB_CONTROL_REQUEST_TYPE_OUT) { + set_endpoint_state(0x80, USB_EP_STATE_STALL); + } else { + set_endpoint_state(0x00, USB_EP_STATE_STALL); + } + } else { + if (ctrlreq_type() != USB_CONTROL_REQUEST_TYPE_OUT) { + int mlen = control_transfer_len; + if (mlen > 64) mlen = 64; + memcpy(ep04_buf, control_transfer_buf, mlen); + R8_UEP0_T_LEN = mlen; + set_endpoint_state(0x80, USB_EP_STATE_ACK); + } else { + set_endpoint_state(0x00, USB_EP_STATE_ACK); + } + } +} diff --git a/src/wang.c b/src/wang.c new file mode 100644 index 0000000..f314ee1 --- /dev/null +++ b/src/wang.c @@ -0,0 +1,184 @@ +#include +#include +#include "CH58x_common.h" +#include "CH58x_sys.h" +#include "CH58xBLE_LIB.h" +#include "ISP583.h" +#include "led.h" +#include "wang.h" +#include "usb/core.h" + +enum state { + RECV_HEADER, + RECV_WIDTHS, + RECV_TIME, + RECV_BLANK, + RECV_DATA, +}; + +__attribute__((aligned(4))) +uint8_t wang_buf[16]; +int wang_buf_pos = 0; +int expected_data_chunks = 0; +int data_chunk_index = 0; +struct wang_header cur_header; + +int wang_rx_inner(const uint8_t *data, int bytes) { + // First try to fill the wang_buf. + int max_bytes = 16 - wang_buf_pos; + int to_copy = bytes; + if (to_copy > max_bytes) to_copy = max_bytes; + + memcpy(wang_buf + wang_buf_pos, data, to_copy); + wang_buf_pos += to_copy; + + if (wang_buf_pos < 16) return to_copy; + + static enum state cur_state = RECV_HEADER; + if (memcmp(wang_buf, "wang\0\0", 6) == 0) { + // We assume "wang\0\0" never happens in real data. + // This is technically a bad assumption, but also, + // who gives a shit. + cur_state = RECV_HEADER; + } else if (cur_state == RECV_HEADER) { + // Assume all our data is properly 16-byte aligned always. + // This is a really sucky assumption, though. + wang_buf_pos = 0; + return to_copy; + } + + switch (cur_state) { + case RECV_HEADER: + memcpy(cur_header.magic, wang_buf, 16); + cur_state = RECV_WIDTHS; + break; + case RECV_WIDTHS: + expected_data_chunks = 0; + for (int i = 0; i < 8; i++) { + cur_header.widths[i] = ((uint16_t)wang_buf[i * 2] << 8) | ((uint16_t)wang_buf[i * 2 + 1]); + expected_data_chunks += cur_header.widths[i] * 11; + } + data_chunk_index = 0; + cur_state = RECV_TIME; + break; + case RECV_TIME: + memcpy(cur_header.padding, wang_buf, 16); + cur_state = RECV_BLANK; + break; + case RECV_BLANK: + memcpy(cur_header.blank, wang_buf, 16); + cur_state = RECV_DATA; + // We are ready to receive the data. This is where things get a bit wonky. + // _erase_ all of flash while we work on this + int to_erase = sizeof(struct wang_header) + expected_data_chunks; + while (to_erase % 16) to_erase++; + if (to_erase < EEPROM_MIN_ER_SIZE) + to_erase = EEPROM_MIN_ER_SIZE; + EEPROM_ERASE(0, to_erase); + break; + case RECV_DATA: + EEPROM_WRITE(sizeof(struct wang_header) + 16 * data_chunk_index, wang_buf, 16); + data_chunk_index++; + if ((data_chunk_index * 16) > expected_data_chunks) { + EEPROM_WRITE(0, (uint8_t *)&cur_header, sizeof(struct wang_header)); + wang_init(); + cur_state = RECV_HEADER; + } + break; + } + + wang_buf_pos = 0; + + return to_copy; +} + +void wang_rx(const uint8_t *data, int length) { + while (length) { + int len = wang_rx_inner(data, length); + data += len; + length -= len; + } +} + +__attribute__((aligned(4))) +struct wang_header flash_header; +int flash_header_valid = 0; +void wang_init(void) { + EEPROM_READ(0, &flash_header, sizeof(struct wang_header)); + if (memcmp(flash_header.magic, "wang\0\0", 6) != 0) { + flash_header_valid = 0; + return; + } + + flash_header_valid = 1; +} + +void wang_render(int index, struct row_buf *output) { + uint16_t width = flash_header.widths[index]; + if (width == 0) return; + + int start_i = sizeof(struct wang_header); + for (int i = 0; i < index; i++) { + start_i += flash_header.widths[i] * 11; + } + + // We oversize this fb to deal with whatever bullshit. + if (width > 6) width = 6; + uint16_t fb[48] = {0}; + + for (int j = 0; j < width; j++) { + // We read a single 11-pixel tall row, and byte-swap it into this screen. + __attribute__((aligned(4))) + uint8_t chunk[11]; + EEPROM_READ(start_i + j * 11, chunk, 11); + + for (int y = 0; y < 11; y++) { + for (int x = 0; x < 8; x++) { + // read most-significant-bit first + if (chunk[y] & (1 << (7 - x))) + fb[j * 8 + x] |= (1 << y); + } + } + } + + display_make_buf_all(fb, output); +} + +void wang_read(int index, int offset, int width, uint16_t *out) { + uint16_t iwidth = flash_header.widths[index]; + if (iwidth == 0) return; + + int start_i = sizeof(struct wang_header); + for (int i = 0; i < index; i++) { + start_i += flash_header.widths[i] * 11; + } + + int start_page = offset / 8; + int end_page = ((offset + width - 1) / 8); + if (end_page >= iwidth) end_page = iwidth - 1; + + int start_x_global = offset; + int end_x_global = offset + width; + uint16_t *out_frobbed = out - start_x_global; + + for (int i = start_page; i <= end_page; i++) { + __attribute__((aligned(4))) + uint8_t chunk[11]; + EEPROM_READ(start_i + i * 11, chunk, 11); + + // Recalculate the start and end x relative to + // our position + int start_x = start_x_global - i * 8; + int end_x = end_x_global - i * 8; + if (start_x < 0) start_x = 0; + if (end_x > 7) end_x = 7; + + uint16_t *out_page = out_frobbed + i * 8; + for (int y = 0; y < 11; y++) { + for (int x = start_x; x <= end_x; x++) { + if (chunk[y] & (1 << (7 - x))) + out_page[x] |= (1 << y); + } + } + } +} diff --git a/src/wang.h b/src/wang.h new file mode 100644 index 0000000..fba6e93 --- /dev/null +++ b/src/wang.h @@ -0,0 +1,30 @@ +#pragma once + +struct wang_header { + // First 16-byte chunk + uint8_t magic[6]; // "wang\0\0" + uint8_t flash_map; + uint8_t marquee_map; + uint8_t speed_and_mode[8]; + + // Second 16-byte chunk + uint16_t widths[8]; + + // Third 16-byte chunk + uint8_t padding[6]; + uint8_t time[6]; + uint8_t padding2[4]; + + // Fourth 16-byte chunk, empty + uint8_t blank[16]; +}; + +// Receive some data in wang format +void wang_rx(const uint8_t *, int); + +extern struct wang_header flash_header; +extern int flash_header_valid; +void wang_init(void); +void wang_render(int index, struct row_buf *output); + +void wang_read(int index, int offset, int width, uint16_t *buf);