1 /* Copyright (C) 2013 Czech Technical University in Prague
5 * - Carlos Jenkins <carlos@jenkins.co.cr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * RPP driver implementation for HBR.
28 // This file contains functions to control H-bridge.
29 // A keep-alive watchdog is implemented.
30 // PWM is available for HBR control.
35 //Flag variable if pwm was initialized and is ready to start.
36 static boolean_t pwm_initialized = FALSE;
39 /// Watchdog Task --------------------------------------------------------------
40 static boolean_t wdg_running = FALSE;
43 // Prepared command to be send on SPI.
44 // Default value is watchdog reset command.
45 uint16_t hbr_spi_wdg_tx = 0x03DB;
47 // Shadow variable of hbr_spi_wdg_tx
48 uint16_t hbr_spi_wdg_tx_shd = 0x03DB;
51 uint16_t hbr_spi_wdg_rx = 0;
53 // Shadow variable of hbr_spi_wdg_shd
54 uint16_t hbr_spi_wdg_rx_shd = 0;
57 * @brief SPI callback function
59 * This function is called each time SPI transfer finishes.
60 * Gets response and prepare command for next sending.
61 * Copy response from shadow variable,
62 * Copy prepared command to shadow variable
64 * @param[in] ifc Pointer to SPI driver structure
65 * @param[in] code SPI transfer status code
66 * @param[in] msg Pointer to message definition structure
70 int drv_hbr_spi_wdg_callback(struct spi_drv* ifc, int code,
71 struct spi_msg_head* msg)
73 if (code == SPI_MSG_FINISHED) {
74 hbr_spi_wdg_rx = hbr_spi_wdg_rx_shd;
75 hbr_spi_wdg_tx_shd = hbr_spi_wdg_tx;
81 // SPI message format definition for watchdog reset command
82 spi_msg_head_t hbr_spi_wdg = {
86 .tx_buf = (uint8_t*) &hbr_spi_wdg_tx_shd,
87 .rx_buf = (uint8_t*) &hbr_spi_wdg_rx_shd,
88 .callback = drv_hbr_spi_wdg_callback,
93 * Watchdog FreeRTOS Task function.
95 * Select appropriate spi address
96 * Initialize task timer
97 * Send watchdog keep-alive command each 10ms.
99 * @param[in] p Pointer to parameter, unused.
101 void drv_hbr_wdg_task(void *p)
104 ifc = spi_find_drv(NULL, 4);
111 portTickType xLastWakeTime;
112 xLastWakeTime = xTaskGetTickCount();
116 spi_msg_rq_ins(ifc, &hbr_spi_wdg);
118 vTaskDelayUntil(&xLastWakeTime, (10 / portTICK_RATE_MS));
123 /// Watchdog API ---------------------------------------------------------------
124 static xTaskHandle wdg_handle = NULL;
127 * Start the watchdog task to send keep-alive commands periodically to H-Bridge.
129 * @return SUCCESS if watchdog could be started.\n
130 * FAILURE if H-Bridge not setup (call drv_hbr_set_signal() first), the
131 * watchdog is running already or the task could not be created.
133 int8_t drv_hbr_wdg_start()
135 if(!pwm_initialized) {
143 // Task already created
144 if(wdg_handle != NULL) {
147 // Task never started
150 if(xTaskCreate(drv_hbr_wdg_task,
151 (const signed char *)"hbr_wdg_task",
152 256, NULL, 1, &wdg_handle) != pdPASS) {
163 * Stop the watchdog task.
165 * @return SUCCESS if watchdog could be stopped.\n
166 * FAILURE if watchdog wasn't running.
168 int8_t drv_hbr_wdg_stop()
170 if(!pwm_initialized) {
183 /// H-Bridge API ---------------------------------------------------------------
185 * @brief Set PWM period and duty cycle to HBR_PWM pin
187 * Set period and dutycycle to HBR_PWM pin.
188 * Period is expected to be in us, duty cycle in percent of the period,
190 * If period is lower than 1 or duty greater than 100, function returns without having effect.
192 * @param[in] period Period of PWM in us
193 * @param[in] duty Width of duty in %
195 int8_t drv_hbr_pwm_set_signal(double period, uint32_t duty)
197 hetSIGNAL_t tmp_signal;
207 tmp_signal.duty = duty;
208 tmp_signal.period = period;
209 pwmSetSignal(hetRAM1, pwm0, tmp_signal);
211 pwm_initialized = TRUE;
218 * Start PWM on HBR_PWM pin
220 * If PWM was set previously by hbr_pwm_set_signal function, this procedure starts it.
221 * Otherwise function returns and PWM is not started.
223 * @return 0 if success, -1 when PWM was not yes set.
225 int8_t drv_hbr_pwm_start()
227 if (pwm_initialized) {
229 pwmStart(hetRAM1, pwm0);
239 * @brief Stop PWM on HBR_PWM pin
241 void drv_hbr_pwm_stop() {
242 pwmStop(hetRAM1, pwm0);
245 void drv_hbr_pwm_set_duty(uint8_t percent)
247 // Don't mind doing range check, pwmSetDuty handles this in error free
249 pwmSetDuty(hetRAM1, pwm0, percent);
253 * @brief Get duty width of PWM on HBR_PWM pin
255 * @return Duty width of PWM in %
257 uint32_t drv_hbr_pwm_get_duty() {
258 hetSIGNAL_t tmp_signal;
259 tmp_signal = pwmGetSignal(hetRAM1, pwm0);
260 return tmp_signal.duty;
264 * @brief Get period of PWM on HBR_PWM pin
266 * @return Period of PWM in us
268 double drv_hbr_pwm_get_period() {
269 hetSIGNAL_t tmp_signal;
270 tmp_signal = pwmGetSignal(hetRAM1, pwm0);
271 return tmp_signal.period;
276 * @brief Set value to HBR_DIR pin.
278 * @param[in] direction If O, set hbr_dir to 0, otherwise to 1
280 void drv_hbr_set_dir(int direction) {
281 hal_gpio_pin_set_value(PIN_DSC_HBRDIR, direction);
285 * @brief Get value of hbr_dir
287 * @return return 0 or 1 - the value of hbr_dir
289 int drv_hbr_get_dir() {
290 return hal_gpio_pin_get_value(PIN_DSC_HBRDIR);
294 * @brief Set value to HBR_EN pin.
296 * @param[in] direction If O, set hbr_en to 0, otherwise to 1
298 void drv_hbr_set_en(int value) {
299 hal_gpio_pin_set_value(PIN_DSC_HBREN, value);
303 * @brief Get value of HBR_EN
305 * @return return 0 or 1 - the value of hbr_en
307 int drv_hbr_get_en() {
308 return hal_gpio_pin_get_value(PIN_DSC_HBREN);