]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/hbridge.c
343d7a0cf9aa4affd2c8cfa4b9a5415f4d90b108
[pes-rpp/rpp-lib.git] / rpp / src / drv / hbridge.c
1 /*
2  * hbridge.c
3  *
4  *  Created on: 9.11.2012
5  *      Author: Michal Horn
6  *
7  *  This file contains functions to control H-bridge.
8  *
9  *  Periodical hbr watchdog reset command sending once it is sent manualy.
10  *  PWM for HBR control
11  */
12
13 //TODO: HBR_DIR and HBR_EN toggling
14
15 //#include "drv_hbridge.h"
16 #include "drv/drv.h"
17
18 /** Flag variable if watchdog command has been sent one before **/
19 static char hbr_spi_initialized;
20 /** Prepared command to be send on SPI, default value is watchdog reset command **/
21 uint16_t hbr_spi_wdg_tx = 0x03DB;
22 /** Response from SPI **/
23 uint16_t hbr_spi_wdg_rx = 0;
24 /** Shadow variable of command being send on SPI, default value is watchdog reset command **/
25 uint16_t hbr_spi_wdg_tx_shd = 0x03DB;
26 /** Response from SPI **/
27 uint16_t hbr_spi_wdg_rx_shd = 0;
28 /** Flag variable if pwm was initialized and is ready to start **/
29 uint8_t hbr_pwm_initialized = 0;
30 /** SPI message format definition for watchdog reset command **/
31 spi_msg_head_t hbr_spi_wdg = {
32         .flags = 0,
33         .addr = 0,
34         .rq_len = 2,
35         .tx_buf = (uint8_t*) &hbr_spi_wdg_tx_shd,
36         .rx_buf = (uint8_t*) &hbr_spi_wdg_rx_shd,
37         .callback = hbr_spi_wdg_callback,
38         .private = 1
39 };
40
41 /**
42  * @brief   Watchdog reset task function
43  *
44  * Select appropriate spi address
45  * Initialize task timer
46  * Send watchdog reset command each 10ms
47  *
48  * @param[in]   pvParameters    Pointer to parameter, not used
49  */
50 void hbr_wdg_task(void *pvParameters) {
51     spi_drv_t *ifc;
52     ifc = spi_find_drv(NULL, 4);
53     if (ifc == NULL)
54         return;
55
56     portTickType xLastWakeTime;
57     xLastWakeTime = xTaskGetTickCount();
58     for( ;; ) {
59         spi_msg_rq_ins(ifc, &hbr_spi_wdg);
60         vTaskDelayUntil( &xLastWakeTime, ( 10 / portTICK_RATE_MS ) );
61     }
62 }
63
64 /**
65  * @brief   SPI callback function
66  *
67  * This function is called each time SPI transfer finishes.
68  * Gets response and prepare command for next sending.
69  * Copy response from shadow variable,
70  * Copy prepared command to shadow variable
71  *
72  * @param[in]   ifc     Pointer to SPI driver structure
73  * @param[in]   code    SPI transfer status code
74  * @param[in]   msg     Pointer to message definition structure
75  *
76  * @return  always zero
77  */
78 int hbr_spi_wdg_callback(struct spi_drv * ifc, int code, struct spi_msg_head * msg) {
79     if (code == SPI_MSG_FINISHED) {
80         hbr_spi_wdg_rx = hbr_spi_wdg_rx_shd;
81         hbr_spi_wdg_tx_shd = hbr_spi_wdg_tx;
82     }
83     return 0;
84 }
85
86 /**
87  * @brief   Start periodically sending watchdog reset commands
88  *
89  * If watchdog command is going to be send for the first time, create new thread and start sending the command each 10ms
90  *
91  * @return SPI response or -1 when thread creation failed.
92  */
93 int hbr_spi_wdg_transfer() {
94     if (!hbr_spi_initialized) {
95         hbr_spi_initialized = 1;
96
97         if (xTaskCreate(hbr_wdg_task, (const signed char *)"HBR_WDG", 300, NULL, 1, NULL ) != pdPASS) {
98             return -1;
99         }
100     }
101     return hbr_spi_wdg_rx;
102 }
103
104 /**
105  * @brief Set PWM period and duty cycle to HBR_PWM pin
106  *
107  * Set period and dutycycle to HBR_PWM pin.
108  * Period is expected to be in us, duty cycle in percent of the period,
109  *
110  * If period is lower than 1 or duty greater than 100, function returns without having effect.
111  *
112  * @param[in]   period      Period of PWM in us
113  * @param[in]   duty        Width of duty in %
114  */
115 void hbr_pwm_set_signal(double period, uint32_t duty)
116 {
117     // FIXME Should not be returning void, the function can not report if it
118     // was successful.
119     hetSIGNAL_t tmp_signal;
120
121     if(duty > 100) {
122         return;
123     }
124
125     if(period < 1) {
126         return;
127     }
128
129     tmp_signal.duty   = duty;
130     tmp_signal.period = period;
131     pwmSetSignal(hetRAM1, pwm0, tmp_signal);
132
133     hbr_pwm_initialized = TRUE;
134 }
135
136 /**
137  * @brief Start PWM on HBR_PWM pin
138  *
139  * If PWM was set previously by hbr_pwm_set_signal function, this procedure starts it.
140  * Otherwise function returns and PWM is not started.
141  *
142  * @return  0 if success, -1 when PWM was not yes set.
143  */
144 int hbr_pwm_start() {
145     if (hbr_pwm_initialized) {
146         pwmStart(hetRAM1, pwm0);
147         return 0;
148     }
149     else {
150         return -1;
151     }
152 }
153
154 /**
155  * @brief Stop PWM on HBR_PWM pin
156  */
157 void hbr_pwm_stop() {
158     pwmStop(hetRAM1, pwm0);
159 }
160
161 void hbr_pwm_set_duty(uint8_t percent)
162 {
163     // Don't mind doing range check, pwmSetDuty handles this in error free
164     // manner.
165     pwmSetDuty(hetRAM1, pwm0, percent);
166 }
167
168 /**
169  * @brief Get duty width of PWM on HBR_PWM pin
170  *
171  * @return      Duty width of PWM in %
172  */
173 uint32_t hbr_pwm_get_duty() {
174     hetSIGNAL_t tmp_signal;
175     tmp_signal = pwmGetSignal(hetRAM1, pwm0);
176     return tmp_signal.duty;
177 }
178
179 /**
180  * @brief Get period of PWM on HBR_PWM pin
181  *
182  * @return      Period of PWM in us
183  */
184 double hbr_pwm_get_period() {
185     hetSIGNAL_t tmp_signal;
186     tmp_signal = pwmGetSignal(hetRAM1, pwm0);
187     return tmp_signal.period;
188
189 }
190
191 /**
192  *  @brief  Set value to HBR_DIR pin.
193  *
194  *  @param[in]  direction   If O, set hbr_dir to 0, otherwise to 1
195  */
196 void hbr_set_dir(int direction) {
197     hal_gpio_pin_set_value(PIN_DSC_HBRDIR, direction);
198 }
199
200 /**
201  *  @brief  Get value of hbr_dir
202  *
203  *  @return return 0 or 1 - the value of hbr_dir
204  */
205 int hbr_get_dir() {
206     return hal_gpio_pin_get_value(PIN_DSC_HBRDIR);
207 }
208
209 /**
210  *  @brief  Set value to HBR_EN pin.
211  *
212  *  @param[in]  direction   If O, set hbr_en to 0, otherwise to 1
213  */
214 void hbr_set_en(int value) {
215     hal_gpio_pin_set_value(PIN_DSC_HBREN, value);
216 }
217
218 /**
219  *  @brief  Get value of HBR_EN
220  *
221  *  @return return 0 or 1 - the value of hbr_en
222  */
223 int hbr_get_en() {
224     return hal_gpio_pin_get_value(PIN_DSC_HBREN);
225 }