|
| 1 | +/* |
| 2 | + Copyright (c) 2017 Daniel Fekete |
| 3 | +
|
| 4 | + Permission is hereby granted, free of charge, to any person obtaining a copy |
| 5 | + of this software and associated documentation files (the "Software"), to deal |
| 6 | + in the Software without restriction, including without limitation the rights |
| 7 | + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 8 | + copies of the Software, and to permit persons to whom the Software is |
| 9 | + furnished to do so, subject to the following conditions: |
| 10 | +
|
| 11 | + The above copyright notice and this permission notice shall be included in all |
| 12 | + copies or substantial portions of the Software. |
| 13 | +
|
| 14 | + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 15 | + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 16 | + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 17 | + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 18 | + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 19 | + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 20 | + SOFTWARE. |
| 21 | +
|
| 22 | + Copyright (c) 2019 STMicroelectronics |
| 23 | + Modified to support Arduino_Core_STM32 |
| 24 | +
|
| 25 | + Modified by TempersLee to support Adruino_Core_CH32 |
| 26 | +*/ |
| 27 | + |
| 28 | +/* Define to prevent recursive inclusion -------------------------------------*/ |
| 29 | +#ifndef HARDWARETIMER_H_ |
| 30 | +#define HARDWARETIMER_H_ |
| 31 | + |
| 32 | +/* Includes ------------------------------------------------------------------*/ |
| 33 | +#include "timer.h" |
| 34 | +#include "ch32yyxx_tim.h" |
| 35 | + |
| 36 | +#if defined(TIM_MODULE_ENABLED) && !defined(TIM_MODULE_ONLY) |
| 37 | + |
| 38 | +#define TIMER_CHANNELS 4 // channel5 and channel 6 are not considered here has they don't have gpio output and they don't have interrupt |
| 39 | + |
| 40 | + |
| 41 | +#define TIM_CHANNEL_CH1 TIM_CC1E /*!< Timer input/output channel 1 */ |
| 42 | +#define TIM_CHANNEL_CH1N TIM_CC1NE /*!< Timer complementary output channel 1 */ |
| 43 | +#define TIM_CHANNEL_CH2 TIM_CC2E /*!< Timer input/output channel 2 */ |
| 44 | +#define TIM_CHANNEL_CH2N TIM_CC2NE /*!< Timer complementary output channel 2 */ |
| 45 | +#define TIM_CHANNEL_CH3 TIM_CC3E /*!< Timer input/output channel 3 */ |
| 46 | +#define TIM_CHANNEL_CH3N TIM_CC3NE /*!< Timer complementary output channel 3 */ |
| 47 | +#define TIM_CHANNEL_CH4 TIM_CC4E /*!< Timer input/output channel 4 */ |
| 48 | + |
| 49 | + |
| 50 | + |
| 51 | +typedef enum { |
| 52 | + TIMER_DISABLED, // == TIM_OCMODE_TIMING no output, useful for only-interrupt |
| 53 | + // Output Compare |
| 54 | + TIMER_OUTPUT_COMPARE, // == Obsolete, use TIMER_DISABLED instead. Kept for compatibility reason |
| 55 | + TIMER_OUTPUT_COMPARE_ACTIVE, // == TIM_OCMODE_ACTIVE pin is set high when counter == channel compare |
| 56 | + TIMER_OUTPUT_COMPARE_INACTIVE, // == TIM_OCMODE_INACTIVE pin is set low when counter == channel compare |
| 57 | + TIMER_OUTPUT_COMPARE_TOGGLE, // == TIM_OCMODE_TOGGLE pin toggles when counter == channel compare |
| 58 | + TIMER_OUTPUT_COMPARE_PWM1, // == TIM_OCMODE_PWM1 pin high when counter < channel compare, low otherwise |
| 59 | + TIMER_OUTPUT_COMPARE_PWM2, // == TIM_OCMODE_PWM2 pin low when counter < channel compare, high otherwise |
| 60 | + TIMER_OUTPUT_COMPARE_FORCED_ACTIVE, // == TIM_OCMODE_FORCED_ACTIVE pin always high |
| 61 | + TIMER_OUTPUT_COMPARE_FORCED_INACTIVE, // == TIM_OCMODE_FORCED_INACTIVE pin always low |
| 62 | + |
| 63 | + //Input capture |
| 64 | + TIMER_INPUT_CAPTURE_RISING, // == TIM_INPUTCHANNELPOLARITY_RISING |
| 65 | + TIMER_INPUT_CAPTURE_FALLING, // == TIM_INPUTCHANNELPOLARITY_FALLING |
| 66 | + TIMER_INPUT_CAPTURE_BOTHEDGE, // == TIM_INPUTCHANNELPOLARITY_BOTHEDGE |
| 67 | + |
| 68 | + // Used 2 channels for a single pin. One channel in TIM_INPUTCHANNELPOLARITY_RISING another channel in TIM_INPUTCHANNELPOLARITY_FALLING. |
| 69 | + // Channels must be used by pair: CH1 with CH2, or CH3 with CH4 |
| 70 | + // This mode is very useful for Frequency and Dutycycle measurement |
| 71 | + TIMER_INPUT_FREQ_DUTY_MEASUREMENT, |
| 72 | + |
| 73 | + TIMER_NOT_USED = 0xFFFF // This must be the last item of this enum |
| 74 | +} TimerModes_t; |
| 75 | + |
| 76 | +typedef enum { |
| 77 | + TICK_FORMAT, // default |
| 78 | + MICROSEC_FORMAT, |
| 79 | + HERTZ_FORMAT, |
| 80 | +} TimerFormat_t; |
| 81 | + |
| 82 | +typedef enum { |
| 83 | + RESOLUTION_1B_COMPARE_FORMAT = 1, // used for Dutycycle: [0 .. 1] |
| 84 | + RESOLUTION_2B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 3] |
| 85 | + RESOLUTION_3B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 7] |
| 86 | + RESOLUTION_4B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 15] |
| 87 | + RESOLUTION_5B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 31] |
| 88 | + RESOLUTION_6B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 63] |
| 89 | + RESOLUTION_7B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 127] |
| 90 | + RESOLUTION_8B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 255] |
| 91 | + RESOLUTION_9B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 511] |
| 92 | + RESOLUTION_10B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 1023] |
| 93 | + RESOLUTION_11B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 2047] |
| 94 | + RESOLUTION_12B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 4095] |
| 95 | + RESOLUTION_13B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 8191] |
| 96 | + RESOLUTION_14B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 16383] |
| 97 | + RESOLUTION_15B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 32767] |
| 98 | + RESOLUTION_16B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 65535] |
| 99 | + |
| 100 | + TICK_COMPARE_FORMAT = 0x80, // default |
| 101 | + MICROSEC_COMPARE_FORMAT, |
| 102 | + HERTZ_COMPARE_FORMAT, |
| 103 | + PERCENT_COMPARE_FORMAT, // used for Dutycycle |
| 104 | +} TimerCompareFormat_t; |
| 105 | + |
| 106 | +#ifdef __cplusplus |
| 107 | + |
| 108 | +#include <functional> |
| 109 | +using callback_function_t = std::function<void(void)>; |
| 110 | + |
| 111 | +/* Class --------------------------------------------------------*/ |
| 112 | +class HardwareTimer { |
| 113 | + public: |
| 114 | + HardwareTimer(); |
| 115 | + HardwareTimer(TIM_TypeDef *instance); |
| 116 | + ~HardwareTimer(); // destructor |
| 117 | + |
| 118 | + void setup(TIM_TypeDef *instance); // Setup, only needed if no instance was passed to the constructor |
| 119 | + |
| 120 | + void pause(void); // Pause counter and all output channels |
| 121 | + void pauseChannel(uint32_t channel); // Timer is still running but channel (output and interrupt) is disabled |
| 122 | + void resume(void); // Resume counter and all output channels |
| 123 | + void resumeChannel(uint32_t channel); // Resume only one channel |
| 124 | + |
| 125 | + void setPrescaleFactor(uint32_t prescaler); // set prescaler register (which is factor value - 1) |
| 126 | + uint32_t getPrescaleFactor(); |
| 127 | + |
| 128 | + void setOverflow(uint32_t val, TimerFormat_t format = TICK_FORMAT); // set AutoReload register depending on format provided |
| 129 | + uint32_t getOverflow(TimerFormat_t format = TICK_FORMAT); // return overflow depending on format provided |
| 130 | + |
| 131 | + void setPWM(uint32_t channel, PinName pin, uint32_t frequency, uint32_t dutycycle, callback_function_t PeriodCallback = nullptr, callback_function_t CompareCallback = nullptr); // Set all in one command freq in HZ, Duty in percentage. Including both interrupt. |
| 132 | + void setPWM(uint32_t channel, uint32_t pin, uint32_t frequency, uint32_t dutycycle, callback_function_t PeriodCallback = nullptr, callback_function_t CompareCallback = nullptr); |
| 133 | + |
| 134 | + void setCount(uint32_t val, TimerFormat_t format = TICK_FORMAT); // set timer counter to value 'val' depending on format provided |
| 135 | + uint32_t getCount(TimerFormat_t format = TICK_FORMAT); // return current counter value of timer depending on format provided |
| 136 | + |
| 137 | + void setMode(uint32_t channel, TimerModes_t mode, PinName pin = NC); // Configure timer channel with specified mode on specified pin if available |
| 138 | + void setMode(uint32_t channel, TimerModes_t mode, uint32_t pin); |
| 139 | + |
| 140 | + TimerModes_t getMode(uint32_t channel); // Retrieve configured mode |
| 141 | + |
| 142 | + void setPreloadEnable(bool value); // Configure overflow preload enable setting |
| 143 | + |
| 144 | + uint32_t getCaptureCompare(uint32_t channel, TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // return Capture/Compare register value of specified channel depending on format provided |
| 145 | + void setCaptureCompare(uint32_t channel, uint32_t compare, TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // set Compare register value of specified channel depending on format provided |
| 146 | + |
| 147 | + void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority); // set interrupt priority |
| 148 | + |
| 149 | + //Add interrupt to period update |
| 150 | + void attachInterrupt(callback_function_t callback); // Attach interrupt callback which will be called upon update event (timer rollover) |
| 151 | + void detachInterrupt(); // remove interrupt callback which was attached to update event |
| 152 | + bool hasInterrupt(); //returns true if a timer rollover interrupt has already been set |
| 153 | + //Add interrupt to capture/compare channel |
| 154 | + void attachInterrupt(uint32_t channel, callback_function_t callback); // Attach interrupt callback which will be called upon compare match event of specified channel |
| 155 | + void detachInterrupt(uint32_t channel); // remove interrupt callback which was attached to compare match event of specified channel |
| 156 | + bool hasInterrupt(uint32_t channel); //returns true if an interrupt has already been set on the channel compare match |
| 157 | + void timerHandleDeinit(); // Timer deinitialization |
| 158 | + |
| 159 | + // Refresh() is useful while timer is running after some registers update |
| 160 | + void refresh(void); // Generate update event to force all registers (Autoreload, prescaler, compare) to be taken into account |
| 161 | + |
| 162 | + uint32_t getTimerClkFreq(); // return timer clock frequency in Hz. |
| 163 | + |
| 164 | + static void captureCompareCallback(TIM_HandleTypeDef *htim); // Generic Capture and Compare callback which will call user callback |
| 165 | + static void updateCallback(TIM_HandleTypeDef *htim); // Generic Update (rollover) callback which will call user callback |
| 166 | + |
| 167 | + void updateRegistersIfNotRunning(TIM_TypeDef *TIMx); // Take into account registers update immediately if timer is not running, |
| 168 | + |
| 169 | + bool isRunning(); // return true if HardwareTimer is running |
| 170 | + bool isRunningChannel(uint32_t channel); // return true if channel is running |
| 171 | + |
| 172 | + // The following function(s) are available for more advanced timer options |
| 173 | + TIM_HandleTypeDef *getHandle(); // return the handle address for HAL related configuration |
| 174 | + int getChannel(uint32_t channel); |
| 175 | + int getLLChannel(uint32_t channel); |
| 176 | + int getIT(uint32_t channel); |
| 177 | + int getAssociatedChannel(uint32_t channel); |
| 178 | +#if defined(TIM_CC1NE) |
| 179 | + bool isComplementaryChannel[TIMER_CHANNELS]; |
| 180 | +#endif |
| 181 | + void TIM_OC_ConfigChannel_Static(TIM_TypeDef *htim, TIM_OCInitTypeDef *sConfig, uint32_t Channel); |
| 182 | + void TIM_IC_ConfigChannel_Static(TIM_TypeDef *htim, TIM_ICInitTypeDef *sConfig, uint32_t Channel); |
| 183 | + |
| 184 | + private: |
| 185 | + TimerModes_t _ChannelMode[TIMER_CHANNELS]; |
| 186 | + timerObj_t _timerObj; |
| 187 | + callback_function_t callbacks[1 + TIMER_CHANNELS]; //Callbacks: 0 for update, 1-4 for channels. (channel5/channel6, if any, doesn't have interrupt) |
| 188 | +}; |
| 189 | + |
| 190 | +extern timerObj_t *HardwareTimer_Handle[TIMER_NUM]; |
| 191 | + |
| 192 | +extern timer_index_t get_timer_index(TIM_TypeDef *htim); |
| 193 | + |
| 194 | +#endif /* __cplusplus */ |
| 195 | + |
| 196 | +#endif // TIM_MODULE_ENABLED && TIM_MODULE_ONLY |
| 197 | +#endif // HARDWARETIMER_H_ |
0 commit comments