1 /* Copyright (C) 2013 Czech Technical University in Prague
4 * - Carlos Jenkins <carlos@jenkins.co.cr>
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.
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.
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/>.
21 * Digital Input RPP API implementation file.
25 * RPP API documentation.
31 #if rppCONFIG_INCLUDE_DIN == 1
33 #if rppCONFIG_DRV == 1
37 static boolean_t initialized = FALSE;
50 // Check for configuration changes to avoid SPI overhead
51 static boolean_t config_changed = FALSE;
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;
58 int8_t rpp_din_setup(uint8_t pin, boolean_t pull_type,
59 boolean_t active, boolean_t can_wake)
62 if((pin < 1) || (pin > 16)) {
66 // Check programmable feature
67 if(pull_type && (pin > 8)) {
72 uint8_t index = pin - 1;
74 bit_set(pull_cache, index);
76 bit_clear(pull_cache, index);
80 bit_set(active_cache, index);
82 bit_clear(active_cache, index);
86 bit_set(can_wake_cache, index);
88 bit_clear(can_wake_cache, index);
91 config_changed = TRUE;
96 static uint16_t in_cache = 0x0;
98 int8_t rpp_din_get(uint8_t pin, boolean_t var_thr)
101 if((pin < 1) || (pin > 16)) {
106 if(var_thr && (pin < 9)) {
110 // Use of variable threshold was requested
112 #if rppCONFIG_DRV == 1
113 if(drv_din_get_varthr(pin - 1) == 1) {
120 if(is_bit_set(in_cache, pin - 1)) {
127 static uint16_t diag_cache = 0x0;
129 int8_t rpp_din_diag(uint8_t pin)
132 if((pin < 1) || (pin > 16)) {
136 if(is_bit_set(diag_cache, pin - 1)) {
143 // Helper function to change bit order.
144 static uint8_t lsb_msb(uint8_t a)
149 for(i = 0 ; i < 8 ; i ++) {
151 b |= ((a & (1 << i)) >> i);
157 int8_t rpp_din_update()
159 #if rppCONFIG_DRV == 1
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)));
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.
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);
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.
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
217 // Mark configuration as commited
218 config_changed = FALSE;
221 // Update cached values
224 in_cache = din_get_val_word();
226 // FIXME: Implement. Dummy assign for now.
227 diag_cache = in_cache;
229 if(diag_cache != in_cache) {
233 UNUSED(config_changed);
240 #endif /* rppCONFIG_INCLUDE_DIN */