]> git.karo-electronics.de Git - oswald.git/blob - metawatch/oswald_hal.c
Add modified LPM3_EXIT_ISR to work around FLL IRQ wake-up problem
[oswald.git] / metawatch / oswald_hal.c
1 /*
2  * Adaptation to Oswald
3  */
4 #include <msp430.h>
5 #include <msp430xgeneric.h>
6 #include <stdint.h>
7 #include <string.h>
8
9 #include "mw_main.h"
10
11 #include "mw_lcd.h"
12 #include "mw_adc.h"
13 #include "mw_bt.h"
14 #include "bt_hci.h"
15 #include "bt_l2cap.h"
16 #include "bluetooth_init_cc256x.h"
17 #include "mw_acc.h"
18
19 #include "oswald.h"
20 #include "oswald_hal.h"
21
22 #include "calendar.h"
23
24
25 const char *hal_get_version_string(void)
26 {
27         return MW_MAIN_VERSION;
28 }
29
30 const char *hal_get_buildno_string(void)
31 {
32         return BUILDNO;
33 }
34
35 const char *hal_get_radio_version_string(void)
36 {
37         return cc256x_version;
38 }
39
40 void hal_lcd_set_pixel(uint8_t x, uint8_t y, uint8_t color)
41 {
42         if (x > 95)
43                 x = 95;
44         if (y > 95)
45                 y = 95;
46         mw_lcd_draw_pixel(x, y, color ? LCD_BLACK : LCD_WHITE);
47 }
48
49 void hal_lcd_clear_display(void)
50 {
51         mw_lcd_clear_fb();
52 }
53
54 void hal_lcd_update_display(void)
55 {
56         mw_lcd_update_screen();
57 }
58
59 void hal_lcd_set_backlight(boolean state)
60 {
61         if (state) {
62                 ENABLE_LCD_LED();
63         } else {
64                 DISABLE_LCD_LED();
65         }
66 }
67
68 boolean hal_lcd_get_backlight(void)
69 {
70         return (LCD_LED_POUT & LCD_LED_PIN) ? TRUE : FALSE;
71 }
72
73 void hal_enable_centisecond_timer(void)
74 {
75         start_timer(TIMER_100MS_CYCLES);
76 }
77
78 void hal_disable_centisecond_timer(void)
79 {
80         stop_timer();
81 }
82
83 void hal_enable_halfsecond_timer(void)
84 {
85         start_timer(TIMER_500MS_CYCLES);
86 }
87
88 void hal_disable_halfsecond_timer(void)
89 {
90         stop_timer();
91 }
92
93 void hal_get_rtc(clock_state *rtc)
94 {
95         /* Update clock state from RTC */
96         rtc->hour = RTCHOUR;
97         rtc->minute = RTCMIN;
98         rtc->second = RTCSEC;
99         rtc->day = RTCDAY;
100         rtc->month = RTCMON;
101         rtc->year = RTCYEAR;
102         rtc->wday = RTCDOW;
103 }
104
105 void hal_set_rtc(clock_state *rtc, boolean set_sec)
106 {
107         /* Update clock state from RTC */
108         RTCHOUR = rtc->hour;
109         RTCMIN = rtc->minute;
110         if (set_sec)
111                 RTCSEC = rtc->second;
112         RTCDAY = rtc->day;
113         RTCMON = rtc->month;
114         RTCYEAR = rtc->year;
115         rtc->wday = getWochentag(rtc->day, rtc->month, rtc->year);
116         RTCDOW = rtc->wday;
117 }
118
119 void hal_get_power_state(power_state *pwr)
120 {
121         unsigned int val;
122
123         pwr->source = (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT) ? POWER_SOURCE_BATTERY : POWER_SOURCE_EXTERNAL;
124
125         /* unless the charger is enabled we do not get a reasonable state */
126         if (!(BAT_CHARGE_IN & BAT_CHARGE_ENABLE_PIN)) {
127                 switch (BAT_CHARGE_IN & (BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2)) {
128                         case BAT_CHARGE_STAT1:
129                                 pwr->charge_state = POWER_CHARGER_DONE;
130                                 break;
131                         case BAT_CHARGE_STAT2:
132                                 pwr->charge_state = POWER_CHARGER_CHARGING;
133                                 break;
134                         case (BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2):
135                                 pwr->charge_state = POWER_CHARGER_UNK;
136                                 break;
137                         default:
138                                 pwr->charge_state = POWER_CHARGER_PRECHARGE;
139                                 break;
140                 }
141         } else {
142                 pwr->charge_state = POWER_CHARGER_UNK;
143         }
144
145         if ((pwr->source == POWER_SOURCE_BATTERY) && (RTCSEC != 0)) {
146                 /* the ADC and activating the measuring shunts is
147                  * power expensive so only do this every minute */
148                 return;
149         };
150
151         /* get new values and so some averaging to avoid jumps */
152         val = mw_get_battery_adc_val();
153         pwr->percent = mw_get_battery_percentage_from_val(val);
154         pwr->level = val;
155 }
156
157 void hal_vibration_set_state(boolean state)
158 {
159 #ifdef MW_DIGITAL_V2
160         if (state) {
161                 TA1CTL |= TASSEL__ACLK | MC__UPDOWN | ID_0;
162                 P7SEL |= BIT3;
163         } else {
164                 TA1CTL = 0;
165                 P7SEL &= ~BIT3;
166         }
167 #endif
168 }
169
170 boolean hal_vibration_get_state(void)
171 {
172 #ifdef MW_DIGITAL_V2
173         return (P7SEL & BIT3) ? TRUE : FALSE;
174 #else
175         return FALSE;
176 #endif
177 }
178
179 #define BLUETOOTH_DEVICE_NAME "Oswald on MetaWatch"
180 static boolean bt_is_visible = FALSE;
181
182
183 bluetooth_state hal_bluetooth_set_state(bluetooth_state state)
184 {
185         uint8_t buf[32];
186
187         if (state == BLUETOOTH_OFF && mw_bt_is_enabled() == 1) {
188                 mw_disable_bt();
189                 bt_is_visible = FALSE;
190                 return BLUETOOTH_OFF;
191         } else if (state == BLUETOOTH_ON && mw_bt_is_enabled() == 0) {
192                 mw_enable_bt();
193                 // set our name
194                 memset(buf, 0, 32);
195                 strncpy((char *)buf, BLUETOOTH_DEVICE_NAME, strlen(BLUETOOTH_DEVICE_NAME));
196                 bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_LOCAL_NAME_OCF, strlen(BLUETOOTH_DEVICE_NAME)+1, buf);
197                 // read our local address
198                 bt_hci_cmd(HCI_INFO_PARAM_OGF, HCI_R_BD_ADDR_OCF, 0, NULL);
199                 // enable page scan
200                 buf[0] = HCI_BB_SCAN_PAGE;
201                 bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_SCAN_EN_OCF, 1, buf);
202                 bt_is_visible = FALSE;
203                 return BLUETOOTH_ON;
204         } else
205                 return BLUETOOTH_ILL;
206 }
207
208 bluetooth_state hal_bluetooth_get_state(void)
209 {
210         if (mw_bt_is_enabled() == 1) {
211                 if (bt_l2cap_get_connected(0x40))
212                         return BLUETOOTH_CONNECTED;
213                 else
214                         return BLUETOOTH_ON;
215         } else
216                 return BLUETOOTH_OFF;
217 }
218
219 uint8_t *hal_bluetooth_get_local_bdaddr(void)
220 {
221         return bt_hci_get_local_bdaddr();
222 }
223
224 void hal_bluetooth_set_visible(boolean visible)
225 {
226         uint8_t buf[2];
227
228         if (mw_bt_is_enabled() == 0) {
229                 bt_is_visible = FALSE;
230                 return;
231         }
232
233         if (visible) {
234                 // enable page and inquiry scan
235                 buf[0] = HCI_BB_SCAN_INQUIRY | HCI_BB_SCAN_PAGE;
236                 bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_SCAN_EN_OCF, 1, buf);
237                 bt_is_visible = TRUE;
238         } else {
239                 // enable page scan only
240                 buf[0] = HCI_BB_SCAN_PAGE;
241                 bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_SCAN_EN_OCF, 1, buf);
242                 bt_is_visible = FALSE;
243         }
244 }
245
246 boolean hal_bluetooth_get_visible(void)
247 {
248         return bt_is_visible;
249 }
250
251 void hal_bluetooth_send_data(const void *mdat, uint16_t mlen)
252 {
253         bt_l2cap_send_channel(0x40, mdat, mlen);
254 }
255
256 /*
257  * Control the accelerometer
258  */
259 void hal_accelerometer_enable(void)
260 {
261         mw_acc_enable();
262 }
263
264 void hal_accelerometer_disable(void)
265 {
266         mw_acc_disable();
267 }
268
269 uint16_t hal_amblight_get_val(void)
270 {
271         return mw_get_amblight_adc_val();
272 }
273