]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/rpp/din.c
I think I fixed the DIN module on RPP. DIN in DRV should NOT receive everything as...
[pes-rpp/rpp-lib.git] / rpp / src / rpp / din.c
1 /* Copyright (C) 2013 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Carlos Jenkins <carlos@jenkins.co.cr>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * File : din.c
20  * Abstract:
21  *     Digital Input RPP API implementation file.
22  *
23  * References:
24  *     din.h
25  *     RPP API documentation.
26  */
27
28
29 #include "rpp/rpp.h"
30
31 #if rppCONFIG_INCLUDE_DIN == 1
32
33 #if rppCONFIG_DRV == 1
34 #include "drv/din.h"
35 #endif
36
37 static boolean_t initialized = FALSE;
38
39 int8_t rpp_din_init()
40 {
41     if(initialized) {
42         return FAILURE;
43     }
44     initialized = TRUE;
45
46     return SUCCESS;
47 }
48
49
50 // Check for configuration changes to avoid SPI overhead
51 static boolean_t config_changed = FALSE;
52
53 // All cached values are 16 bits in the form [SG7,...,SG0][SP7,...,SP0]
54 static uint16_t pull_cache     = 0x0;
55 static uint16_t active_cache   = 0x0;
56 static uint16_t can_wake_cache = 0x0;
57
58 int8_t rpp_din_setup(uint8_t pin, boolean_t pull_type,
59                       boolean_t active, boolean_t can_wake)
60 {
61     // Check range
62     if((pin < 1) || (pin > 16)) {
63         return -1;
64     }
65
66     // Check programmable feature
67     if(pull_type && (pin > 8)) {
68         return -2;
69     }
70
71     // Set bits
72     uint8_t index = pin - 1;
73     if(pull_type) {
74         bit_set(pull_cache, index);
75     } else {
76         bit_clear(pull_cache, index);
77     }
78
79     if(active) {
80         bit_set(active_cache, index);
81     } else {
82         bit_clear(active_cache, index);
83     }
84
85     if(can_wake) {
86         bit_set(can_wake_cache, index);
87     } else {
88         bit_clear(can_wake_cache, index);
89     }
90
91     config_changed = TRUE;
92     return SUCCESS;
93 }
94
95
96 static uint16_t in_cache = 0x0;
97
98 int8_t rpp_din_get(uint8_t pin, boolean_t var_thr)
99 {
100     // Check range
101     if((pin < 1) || (pin > 16)) {
102         return -1;
103     }
104
105     // Check feature
106     if(var_thr && (pin < 9)) {
107         return -2;
108     }
109
110     // Use of variable threshold was requested
111     if(var_thr) {
112         #if rppCONFIG_DRV == 1
113         if(drv_din_get_varthr(pin - 1) == 1) {
114             return HIGH;
115         }
116         #endif
117         return LOW;
118     }
119
120     if(is_bit_set(in_cache, pin - 1)) {
121         return HIGH;
122     }
123     return LOW;
124 }
125
126
127 static uint16_t diag_cache = 0x0;
128
129 int8_t rpp_din_diag(uint8_t pin)
130 {
131     // Check range
132     if((pin < 1) || (pin > 16)) {
133         return -1;
134     }
135
136     if(is_bit_set(diag_cache, pin - 1)) {
137         return HIGH;
138     }
139     return LOW;
140 }
141
142
143 // Helper function to change bit order.
144 static uint8_t lsb_msb(uint8_t a)
145 {
146     uint8_t i;
147     uint8_t b = 0;
148
149     for(i = 0 ; i < 8 ; i ++) {
150         b <<= 1;
151         b |= ((a & (1 << i)) >> i);
152     }
153     return b;
154 }
155
156
157 int8_t rpp_din_update()
158 {
159     #if rppCONFIG_DRV == 1
160     /// Setup pins
161     if(config_changed) {
162         uint16_t sp = 0x0;
163         uint16_t sg = 0x0;
164
165         // Set pull-type.
166         // In DRV logic is inverted:
167         // DRV: 1 - set pin as switch-to-battery. RPP: 0 - pull-down.
168         // DRV: 0 - set pin as switch-to-ground.  RPP: 1 - pull-up.
169         // Also DRV is MSB and not LSB:
170         // DRV: [SP0,...,SP7]. RPP: [SG7,...,SG0][SP7,...,SP0].
171         din_set_pr(lsb_msb((uint8_t) ~(pull_cache & 0xFF)));
172         din_spi_transfer();
173
174         // Set state type, active or tri-stated.
175         // In DRV logic is inverted:
176         // DRV: 1 - tri-state. RPP: 0 - tri-state.
177         // DRV: 0 - active.    RPP: 1 - active.
178         // Also DRV is MSB and not LSB:
179         // DRV: SP - [SP0,...,SP7,X8,...,X15]. RPP: SG/SP - [SG7,...,SG0][SP7,...,SP0].
180         // DRV: SG - [SG0,...,SG13,...,  X15]. RPP: SG/SP - [SG7,...,SG0][SP7,...,SP0].
181         sp = (((uint16_t) lsb_msb(~((uint8_t) (active_cache & 0xFF)))) << 8) | 0x00FF;
182         sg = (((uint16_t) lsb_msb(~((uint8_t) (active_cache >> 8  )))) << 8) | 0x00FF;
183         // Debug help (on sg):
184         // 1) Extract the SG bits from active_cache by shifting 8 bits to the right.
185         // 2) Convert that 0b00000000xyyyyyyz 16bits number to a 8 bits number 0bxyyyyyyz.
186         // 3) Bit negate that 8 bit number to match inverted logic in DRV 0bijjjjjjk.
187         // 4) Convert from LSB (as in RPP) to MSB (as in DRV) using lsb_msb.
188         //      0bkjjjjjji
189         // 5) Convert back this 8bit number to 16bits number and shift 8 bits to the left:
190         //      0bkjjjjjji00000000
191         // 6) SG8-SG13 should always be tri-stated ('1') as they are not connected on the board.
192         //      0bkjjjjjji11111111
193         din_set_stat(sp, sg);
194         din_spi_transfer();
195
196         // Set wake / interrupt.
197         // IN DRV logic is not inverted.
198         // DRV: 1 - can wake.           RPP: 1 - can wake.
199         // DRV: 0 - interrupt disabled. RPP: 0 - interrupt disabled.
200         // But DRV is MSB and not LSB:
201         // DRV: SP - [SP0,...,SP7,X8,...,X15]. RPP: SG/SP - [SG7,...,SG0][SP7,...,SP0].
202         // DRV: SG - [SG0,...,SG13,...,  X15]. RPP: SG/SP - [SG7,...,SG0][SP7,...,SP0].
203         sp = (((uint16_t) lsb_msb((uint8_t) (can_wake_cache & 0xFF))) << 8) & 0xFF00;
204         sg = (((uint16_t) lsb_msb((uint8_t) (can_wake_cache >> 8  ))) << 8) & 0xFF00;
205         // Debug help (on sg):
206         // 1) Extract the SG bits from active_cache by shifting 8 bits to the right.
207         // 2) Convert that 0b00000000xyyyyyyz 16bits number to a 8 bits number 0bxyyyyyyz.
208         // 3) Convert from LSB (as in RPP) to MSB (as in DRV) using lsb_msb.
209         //      0bzyyyyyyx
210         // 4) Convert back this 8bit number to 16bits number and shift 8 bits to the left:
211         //      0bzyyyyyyx00000000
212         // 5) SG8-SG13 should always be non-interrupt ('0') as they are not connected on the board.
213         //      0bzyyyyyyx00000000
214         din_set_int(sp, sg);
215         din_spi_transfer();
216
217         // Mark configuration as commited
218         config_changed = FALSE;
219     }
220
221     // Update cached values
222     din_switch_st();
223     din_spi_transfer();
224     in_cache = din_get_val_word();
225
226     // FIXME: Implement. Dummy assign for now.
227     diag_cache = in_cache;
228
229     if(diag_cache != in_cache) {
230         return FAILURE;
231     }
232     #else
233     UNUSED(config_changed);
234     #endif
235
236     return SUCCESS;
237 }
238
239
240 #endif /* rppCONFIG_INCLUDE_DIN */
241