]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/rpp/hbr.c
Make the RPP layer thread safe
[pes-rpp/rpp-lib.git] / rpp / src / rpp / hbr.c
1 /* Copyright (C) 2013, 2014, 2015 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Carlos Jenkins <carlos@jenkins.co.cr>
5  *
6  * This document contains proprietary information belonging to Czech
7  * Technical University in Prague. Passing on and copying of this
8  * document, and communication of its contents is not permitted
9  * without prior written authorization.
10  *
11  * File : hbr.c
12  * Abstract:
13  *     H-Bridge Output RPP API implementation file.
14  *
15  * References:
16  *     hbr.h
17  *     RPP API documentation.
18  */
19
20
21 #include "rpp/rpp.h"
22 #include "rpp/mutex.h"
23
24 #ifndef FREERTOS_POSIX
25 #include "drv/hbridge.h"
26 #include "drv/spi_tms570.h"
27 #endif
28
29 RPP_MUTEX_DEFINE(mutex_hbr);
30
31 static boolean_t initialized = FALSE;
32
33 int8_t rpp_hbr_init()
34 {
35         if (initialized)
36                 return FAILURE;
37         if (!RPP_MUTEX_INIT(mutex_hbr))
38                 return FAILURE;
39         initialized = TRUE;
40 #ifndef FREERTOS_POSIX
41         dmmInit();
42         hetInit();
43         spi_tms570_init();
44 #endif
45         return SUCCESS;
46 }
47
48
49 // Private function to set the H-Bridge to default OFF settings
50 static void rpp_hdr_reset()
51 {
52 #ifndef FREERTOS_POSIX
53         drv_hbr_set_en(LOW);
54         drv_hbr_pwm_set_duty(0);
55         drv_hbr_pwm_stop();
56         drv_hbr_set_dir(LOW);
57 #endif
58 }
59
60
61 static boolean_t enabled = FALSE;
62
63 int8_t rpp_hbr_enable(int32_t period)
64 {
65         if (enabled)
66                 return FAILURE;
67
68         if (period < 1)
69                 period = 55;  // ~18kHz (18181.818181818 Hz to be precise)
70
71 #ifndef FREERTOS_POSIX
72         RPP_MUTEX_LOCK(mutex_hbr);
73         rpp_hdr_reset();
74
75         // Configure N2HET
76         if (drv_hbr_pwm_set_signal(period, 0) != SUCCESS) {
77                 RPP_MUTEX_UNLOCK(mutex_hbr);
78                 return FAILURE;
79         }
80         drv_hbr_pwm_start();
81
82         drv_hbr_set_en(HIGH);
83
84         // Start watchdog
85         int ret = drv_hbr_wdg_start();
86         if (ret != SUCCESS && ret != -RPP_EBUSY) {   // Don't fail if already started
87                 RPP_MUTEX_UNLOCK(mutex_hbr);
88                 return FAILURE;
89         }
90         RPP_MUTEX_UNLOCK(mutex_hbr);
91 #endif
92
93         enabled = TRUE;
94
95         return SUCCESS;
96 }
97
98
99 int8_t rpp_hbr_control(double cmd)
100 {
101         if (!enabled)
102                 return -1;
103
104         // Check range of the command
105         if ((cmd < -1.0) || (cmd > 1.0))
106                 return -2;
107
108 #ifndef FREERTOS_POSIX
109         // Great, now scale and return to sanity world of ints :D
110         int32_t scaled = (int32_t)(cmd * 100.0);
111
112
113         // Set direction
114         RPP_MUTEX_LOCK(mutex_hbr);
115         drv_hbr_set_dir(scaled > 0);
116
117         // Set PWM duty cycle
118         drv_hbr_pwm_set_duty(abs(scaled));
119         RPP_MUTEX_UNLOCK(mutex_hbr);
120 #endif
121
122         return SUCCESS;
123 }
124
125
126 int8_t rpp_hbr_disable()
127 {
128         if (!enabled)
129                 return FAILURE;
130
131 #ifndef FREERTOS_POSIX
132         RPP_MUTEX_LOCK(mutex_hbr);
133         rpp_hdr_reset();
134
135         // We ignore is watchdog could not be stopped, because is harmless.
136         // It would be worse if we just could not stop the H-Bridge just because
137         // the watchdog could not be stopped.
138         drv_hbr_wdg_stop();
139         RPP_MUTEX_UNLOCK(mutex_hbr);
140 #endif
141
142         enabled = FALSE;
143
144         return SUCCESS;
145 }