-/*
- * hbridge.c
+/* Copyright (C) 2013 Czech Technical University in Prague
*
- * Created on: 9.11.2012
- * Author: Michal Horn
+ * Authors:
+ * - Michal Horn
+ * - Carlos Jenkins <carlos@jenkins.co.cr>
*
- * This file contains functions to control H-bridge.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * Periodical hbr watchdog reset command sending once it is sent manualy.
- * PWM for HBR control
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * File : ain.c
+ * Abstract:
+ * RPP driver implementation for HBR.
+ *
+ * References:
+ * hbridge.h
*/
-//TODO: HBR_DIR and HBR_EN toggling
+// This file contains functions to control H-bridge.
+// A keep-alive watchdog is implemented.
+// PWM is available for HBR control.
+
-//#include "drv_hbridge.h"
#include "drv/drv.h"
-/** Flag variable if watchdog command has been sent one before **/
-static char hbr_spi_initialized;
-/** Prepared command to be send on SPI, default value is watchdog reset command **/
+//Flag variable if pwm was initialized and is ready to start.
+static boolean_t pwm_initialized = FALSE;
+
+
+/// Watchdog Task --------------------------------------------------------------
+
+// Prepared command to be send on SPI.
+// Default value is watchdog reset command.
uint16_t hbr_spi_wdg_tx = 0x03DB;
-/** Response from SPI **/
-uint16_t hbr_spi_wdg_rx = 0;
-/** Shadow variable of command being send on SPI, default value is watchdog reset command **/
+
+// Shadow variable of hbr_spi_wdg_tx
uint16_t hbr_spi_wdg_tx_shd = 0x03DB;
-/** Response from SPI **/
+
+// Response from SPI.
+uint16_t hbr_spi_wdg_rx = 0;
+
+// Shadow variable of hbr_spi_wdg_shd
uint16_t hbr_spi_wdg_rx_shd = 0;
-/** Flag variable if pwm was initialized and is ready to start **/
-uint8_t hbr_pwm_initialized = 0;
-/** SPI message format definition for watchdog reset command **/
+
+/**
+ * @brief SPI callback function
+ *
+ * This function is called each time SPI transfer finishes.
+ * Gets response and prepare command for next sending.
+ * Copy response from shadow variable,
+ * Copy prepared command to shadow variable
+ *
+ * @param[in] ifc Pointer to SPI driver structure
+ * @param[in] code SPI transfer status code
+ * @param[in] msg Pointer to message definition structure
+ *
+ * @return always zero
+ */
+int drv_hbr_spi_wdg_callback(struct spi_drv* ifc, int code,
+ struct spi_msg_head* msg)
+{
+ if (code == SPI_MSG_FINISHED) {
+ hbr_spi_wdg_rx = hbr_spi_wdg_rx_shd;
+ hbr_spi_wdg_tx_shd = hbr_spi_wdg_tx;
+ }
+ return 0;
+}
+
+
+// SPI message format definition for watchdog reset command
spi_msg_head_t hbr_spi_wdg = {
.flags = 0,
.addr = 0,
.rq_len = 2,
.tx_buf = (uint8_t*) &hbr_spi_wdg_tx_shd,
.rx_buf = (uint8_t*) &hbr_spi_wdg_rx_shd,
- .callback = hbr_spi_wdg_callback,
+ .callback = drv_hbr_spi_wdg_callback,
.private = 1
};
/**
- * @brief Watchdog reset task function
+ * Watchdog FreeRTOS Task function.
*
* Select appropriate spi address
* Initialize task timer
- * Send watchdog reset command each 10ms
+ * Send watchdog keep-alive command each 10ms.
*
- * @param[in] pvParameters Pointer to parameter, not used
+ * @param[in] p Pointer to parameter, unused.
*/
-void hbr_wdg_task(void *pvParameters) {
- spi_drv_t *ifc;
+void drv_hbr_wdg_task(void *p)
+{
+ spi_drv_t* ifc;
ifc = spi_find_drv(NULL, 4);
- if (ifc == NULL)
- return;
+
+ if(ifc == NULL) {
+ vTaskSuspend(NULL);
+ }
portTickType xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
- for( ;; ) {
+ while(TRUE) {
spi_msg_rq_ins(ifc, &hbr_spi_wdg);
- vTaskDelayUntil( &xLastWakeTime, ( 10 / portTICK_RATE_MS ) );
+ vTaskDelayUntil(&xLastWakeTime, (10 / portTICK_RATE_MS));
}
}
+
+/// Watchdog API ---------------------------------------------------------------
+static boolen_t wdg_running = FALSE;
+static xTaskHandle wdg_handle = NULL;
+
/**
- * @brief SPI callback function
- *
- * This function is called each time SPI transfer finishes.
- * Gets response and prepare command for next sending.
- * Copy response from shadow variable,
- * Copy prepared command to shadow variable
+ * Start the watchdog task to send keep-alive commands periodically to H-Bridge.
*
- * @param[in] ifc Pointer to SPI driver structure
- * @param[in] code SPI transfer status code
- * @param[in] msg Pointer to message definition structure
- *
- * @return always zero
+ * @return SUCCESS if watchdog could be started.\n
+ * FAILURE if H-Bridge not setup (call hbr_set_signal() first), the
+ * watchdog is running already or the task could not be created.
*/
-int hbr_spi_wdg_callback(struct spi_drv * ifc, int code, struct spi_msg_head * msg) {
- if (code == SPI_MSG_FINISHED) {
- hbr_spi_wdg_rx = hbr_spi_wdg_rx_shd;
- hbr_spi_wdg_tx_shd = hbr_spi_wdg_tx;
+int8_t drv_hbr_wdg_start()
+{
+ if(!pwm_initialized) {
+ return FAILURE;
}
- return 0;
+
+ if(wdg_running) {
+ return FAILURE;
+ }
+
+ if(xTaskCreate(drv_hbr_wdg_task,
+ (const signed char *)"hbr_wdg_task",
+ 300, NULL, 1, &wdg_handle) != pdPASS) {
+ return FAILURE;
+ }
+
+ wdg_running = TRUE;
+ return SUCCESS;
}
+
/**
- * @brief Start periodically sending watchdog reset commands
- *
- * If watchdog command is going to be send for the first time, create new thread and start sending the command each 10ms
+ * Stop the watchdog task.
*
- * @return SPI response or -1 when thread creation failed.
+ * @return SUCCESS if watchdog could be stopped.\n
+ * FAILURE if watchdog wasn't running.
*/
-int hbr_spi_wdg_transfer() {
- if (!hbr_spi_initialized) {
- hbr_spi_initialized = 1;
+int8_t drv_hbr_wdg_stop()
+{
+ if(!pwm_initialized) {
+ return FAILURE;
+ }
- if (xTaskCreate(hbr_wdg_task, (const signed char *)"HBR_WDG", 300, NULL, 1, NULL ) != pdPASS) {
- return -1;
- }
+ if(!wdg_running) {
+ return FAILURE;
}
- return hbr_spi_wdg_rx;
+
+ vTaskDelete(&wdg_handle);
+ wdg_running = FALSE;
+ return SUCCESS;
}
+
+/// H-Bridge API ---------------------------------------------------------------
/**
* @brief Set PWM period and duty cycle to HBR_PWM pin
*
* @param[in] period Period of PWM in us
* @param[in] duty Width of duty in %
*/
-void hbr_pwm_set_signal(double period, uint32_t duty)
+int8_t drv_hbr_pwm_set_signal(double period, uint32_t duty)
{
- // FIXME Should not be returning void, the function can not report if it
- // was successful.
hetSIGNAL_t tmp_signal;
if(duty > 100) {
- return;
+ return FAILURE;
}
if(period < 1) {
- return;
+ return FAILURE;
}
tmp_signal.duty = duty;
tmp_signal.period = period;
pwmSetSignal(hetRAM1, pwm0, tmp_signal);
- hbr_pwm_initialized = TRUE;
+ pwm_initialized = TRUE;
+
+ return SUCCESS;
}
+
/**
- * @brief Start PWM on HBR_PWM pin
+ * Start PWM on HBR_PWM pin
*
* If PWM was set previously by hbr_pwm_set_signal function, this procedure starts it.
* Otherwise function returns and PWM is not started.
*
* @return 0 if success, -1 when PWM was not yes set.
*/
-int hbr_pwm_start() {
- if (hbr_pwm_initialized) {
+int8_t drv_hbr_pwm_start()
+{
+ if (pwm_initialized) {
+
pwmStart(hetRAM1, pwm0);
- return 0;
- }
- else {
- return -1;
+ return SUCCESS;
+
+ } else {
+
+ return FAILURE;
}
}
/**
* @brief Stop PWM on HBR_PWM pin
*/
-void hbr_pwm_stop() {
+void drv_hbr_pwm_stop() {
pwmStop(hetRAM1, pwm0);
}
*
* @return Duty width of PWM in %
*/
-uint32_t hbr_pwm_get_duty() {
+uint32_t drv_hbr_pwm_get_duty() {
hetSIGNAL_t tmp_signal;
tmp_signal = pwmGetSignal(hetRAM1, pwm0);
return tmp_signal.duty;
*
* @return Period of PWM in us
*/
-double hbr_pwm_get_period() {
+double drv_hbr_pwm_get_period() {
hetSIGNAL_t tmp_signal;
tmp_signal = pwmGetSignal(hetRAM1, pwm0);
return tmp_signal.period;
*
* @param[in] direction If O, set hbr_dir to 0, otherwise to 1
*/
-void hbr_set_dir(int direction) {
+void drv_hbr_set_dir(int direction) {
hal_gpio_pin_set_value(PIN_DSC_HBRDIR, direction);
}
*
* @return return 0 or 1 - the value of hbr_dir
*/
-int hbr_get_dir() {
+int drv_hbr_get_dir() {
return hal_gpio_pin_get_value(PIN_DSC_HBRDIR);
}
*
* @param[in] direction If O, set hbr_en to 0, otherwise to 1
*/
-void hbr_set_en(int value) {
+void drv_hbr_set_en(int value) {
hal_gpio_pin_set_value(PIN_DSC_HBREN, value);
}
*
* @return return 0 or 1 - the value of hbr_en
*/
-int hbr_get_en() {
+int drv_hbr_get_en() {
return hal_gpio_pin_get_value(PIN_DSC_HBREN);
}