diff options
author | Joey Castillo <jose.castillo@gmail.com> | 2021-08-02 13:48:35 -0400 |
---|---|---|
committer | Joey Castillo <jose.castillo@gmail.com> | 2021-08-02 14:36:04 -0400 |
commit | 34945d78e933fc62bedcc975e88be02a0b7fcc2e (patch) | |
tree | 317edc18fe08d76a1f5d8c3aabf88cf58ba73897 /watch-library/hal/src | |
parent | 2d1e2e8c76623543817f4c62b26fc300c1fd0d2c (diff) | |
download | Sensor-Watch-34945d78e933fc62bedcc975e88be02a0b7fcc2e.tar.gz Sensor-Watch-34945d78e933fc62bedcc975e88be02a0b7fcc2e.tar.bz2 Sensor-Watch-34945d78e933fc62bedcc975e88be02a0b7fcc2e.zip |
major project reorg, move library one level up
Diffstat (limited to 'watch-library/hal/src')
-rw-r--r-- | watch-library/hal/src/hal_adc_sync.c | 244 | ||||
-rw-r--r-- | watch-library/hal/src/hal_atomic.c | 66 | ||||
-rw-r--r-- | watch-library/hal/src/hal_calendar.c | 643 | ||||
-rw-r--r-- | watch-library/hal/src/hal_delay.c | 80 | ||||
-rw-r--r-- | watch-library/hal/src/hal_ext_irq.c | 188 | ||||
-rw-r--r-- | watch-library/hal/src/hal_gpio.c | 44 | ||||
-rw-r--r-- | watch-library/hal/src/hal_i2c_m_sync.c | 258 | ||||
-rw-r--r-- | watch-library/hal/src/hal_init.c | 47 | ||||
-rw-r--r-- | watch-library/hal/src/hal_io.c | 63 | ||||
-rw-r--r-- | watch-library/hal/src/hal_pwm.c | 160 | ||||
-rw-r--r-- | watch-library/hal/src/hal_slcd_sync.c | 150 | ||||
-rw-r--r-- | watch-library/hal/src/hal_sleep.c | 73 |
12 files changed, 2016 insertions, 0 deletions
diff --git a/watch-library/hal/src/hal_adc_sync.c b/watch-library/hal/src/hal_adc_sync.c new file mode 100644 index 00000000..33e0d929 --- /dev/null +++ b/watch-library/hal/src/hal_adc_sync.c @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief ADC functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +/** + * \brief Indicates HAL being compiled. Must be defined before including. + */ +#define _COMPILING_HAL + +#include "hal_adc_sync.h" +#include <utils_assert.h> + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Maximum amount of ADC interface instances + */ +#define MAX_ADC_AMOUNT ADC_INST_NUM + +/** + * \brief Initialize ADC + */ +int32_t adc_sync_init(struct adc_sync_descriptor *const descr, void *const hw, void *const func) +{ + ASSERT(descr && hw); + + return _adc_sync_init(&descr->device, hw); +} + +/** + * \brief Deinitialize ADC + */ +int32_t adc_sync_deinit(struct adc_sync_descriptor *const descr) +{ + ASSERT(descr); + _adc_sync_deinit(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Enable ADC + */ +int32_t adc_sync_enable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_enable_channel(&descr->device, channel); + + return ERR_NONE; +} + +/** + * \brief Disable ADC + */ +int32_t adc_sync_disable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_disable_channel(&descr->device, channel); + return ERR_NONE; +} + +/* + * \brief Read data from ADC + */ +int32_t adc_sync_read_channel(struct adc_sync_descriptor *const descr, const uint8_t channel, uint8_t *const buffer, + const uint16_t length) +{ + uint8_t data_size; + uint16_t offset = 0; + + ASSERT(descr && buffer && length); + data_size = _adc_sync_get_data_size(&descr->device); + ASSERT(!(length % data_size)); + + do { + uint16_t result; + _adc_sync_convert(&descr->device); + + while (!_adc_sync_is_channel_conversion_done(&descr->device, channel)) + ; + + result = _adc_sync_read_channel_data(&descr->device, channel); + buffer[offset] = result; + if (1 < data_size) { + buffer[offset + 1] = result >> 8; + } + offset += data_size; + } while (offset < length); + + return offset; +} + +/** + * \brief Set ADC reference source + */ +int32_t adc_sync_set_reference(struct adc_sync_descriptor *const descr, const adc_reference_t reference) +{ + ASSERT(descr); + _adc_sync_set_reference_source(&descr->device, reference); + + return ERR_NONE; +} + +/** + * \brief Set ADC resolution + */ +int32_t adc_sync_set_resolution(struct adc_sync_descriptor *const descr, const adc_resolution_t resolution) +{ + ASSERT(descr); + _adc_sync_set_resolution(&descr->device, resolution); + + return ERR_NONE; +} + +/** + * \brief Set ADC input source of a channel + */ +int32_t adc_sync_set_inputs(struct adc_sync_descriptor *const descr, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_set_inputs(&descr->device, pos_input, neg_input, channel); + + return ERR_NONE; +} + +/** + * \brief Set ADC thresholds + */ +int32_t adc_sync_set_thresholds(struct adc_sync_descriptor *const descr, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + ASSERT(descr); + _adc_sync_set_thresholds(&descr->device, low_threshold, up_threshold); + + return ERR_NONE; +} + +/** + * \brief Set ADC gain + */ +int32_t adc_sync_set_channel_gain(struct adc_sync_descriptor *const descr, const uint8_t channel, const adc_gain_t gain) +{ + ASSERT(descr); + _adc_sync_set_channel_gain(&descr->device, channel, gain); + + return ERR_NONE; +} + +/** + * \brief Set ADC conversion mode + */ +int32_t adc_sync_set_conversion_mode(struct adc_sync_descriptor *const descr, const enum adc_conversion_mode mode) +{ + ASSERT(descr); + _adc_sync_set_conversion_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Set ADC differential mode + */ +int32_t adc_sync_set_channel_differential_mode(struct adc_sync_descriptor *const descr, const uint8_t channel, + const enum adc_differential_mode mode) +{ + ASSERT(descr); + _adc_sync_set_channel_differential_mode(&descr->device, channel, mode); + + return ERR_NONE; +} + +/** + * \brief Set ADC window mode + */ +int32_t adc_sync_set_window_mode(struct adc_sync_descriptor *const descr, const adc_window_mode_t mode) +{ + ASSERT(descr); + _adc_sync_set_window_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Retrieve threshold state + */ +int32_t adc_sync_get_threshold_state(const struct adc_sync_descriptor *const descr, adc_threshold_status_t *const state) +{ + ASSERT(descr && state); + _adc_sync_get_threshold_state(&descr->device, state); + + return ERR_NONE; +} + +/** + * \brief Check if conversion is complete + */ +int32_t adc_sync_is_channel_conversion_complete(const struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + return _adc_sync_is_channel_conversion_done(&descr->device, channel); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t adc_sync_get_version(void) +{ + return DRIVER_VERSION; +} + +//@} diff --git a/watch-library/hal/src/hal_atomic.c b/watch-library/hal/src/hal_atomic.c new file mode 100644 index 00000000..f56418ee --- /dev/null +++ b/watch-library/hal/src/hal_atomic.c @@ -0,0 +1,66 @@ +/** + * \file + * + * \brief Critical sections related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_atomic.h" + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Disable interrupts, enter critical section + */ +void atomic_enter_critical(hal_atomic_t volatile *atomic) +{ + *atomic = __get_PRIMASK(); + __disable_irq(); + __DMB(); +} + +/** + * \brief Exit atomic section + */ +void atomic_leave_critical(hal_atomic_t volatile *atomic) +{ + __DMB(); + __set_PRIMASK(*atomic); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t atomic_get_version(void) +{ + return DRIVER_VERSION; +} diff --git a/watch-library/hal/src/hal_calendar.c b/watch-library/hal/src/hal_calendar.c new file mode 100644 index 00000000..842cfb88 --- /dev/null +++ b/watch-library/hal/src/hal_calendar.c @@ -0,0 +1,643 @@ +/** + * \file + * + * \brief Generic CALENDAR functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_calendar.h" +#include <utils.h> +#include <utils_assert.h> +#include <hal_atomic.h> + +#define CALENDAR_VERSION 0x00000001u +#define SECS_IN_LEAP_YEAR 31622400 +#define SECS_IN_NON_LEAP_YEAR 31536000 +#define SECS_IN_31DAYS 2678400 +#define SECS_IN_30DAYS 2592000 +#define SECS_IN_29DAYS 2505600 +#define SECS_IN_28DAYS 2419200 +#define SECS_IN_DAY 86400 +#define SECS_IN_HOUR 3600 +#define SECS_IN_MINUTE 60 +#define DEFAULT_BASE_YEAR 1970 + +#define SET_ALARM_BUSY 1 +#define PROCESS_ALARM_BUSY 2 + +/** \brief leap year check + * \retval false not leap year. + * \retval true leap year. + */ +static bool leap_year(uint16_t year) +{ + if (year & 3) { + return false; + } else { + return true; + } +} + +/** \brief calculate the seconds in specified year/month + * \retval 0 month error. + */ +static uint32_t get_secs_in_month(uint32_t year, uint8_t month) +{ + uint32_t sec_in_month = 0; + + if (leap_year(year)) { + switch (month) { + case 1: + case 3: + case 5: + case 7: + case 8: + case 10: + case 12: + sec_in_month = SECS_IN_31DAYS; + break; + case 2: + sec_in_month = SECS_IN_29DAYS; + break; + case 4: + case 6: + case 9: + case 11: + sec_in_month = SECS_IN_30DAYS; + break; + default: + break; + } + } else { + switch (month) { + case 1: + case 3: + case 5: + case 7: + case 8: + case 10: + case 12: + sec_in_month = SECS_IN_31DAYS; + break; + case 2: + sec_in_month = SECS_IN_28DAYS; + break; + case 4: + case 6: + case 9: + case 11: + sec_in_month = SECS_IN_30DAYS; + break; + default: + break; + } + } + + return sec_in_month; +} + +/** \brief convert timestamp to date/time + */ +static int32_t convert_timestamp_to_datetime(struct calendar_descriptor *const calendar, uint32_t ts, + struct calendar_date_time *dt) +{ + uint32_t tmp, sec_in_year, sec_in_month; + uint32_t tmp_year = calendar->base_year; + uint8_t tmp_month = 1; + uint8_t tmp_day = 1; + uint8_t tmp_hour = 0; + uint8_t tmp_minutes = 0; + + tmp = ts; + + /* Find year */ + while (true) { + sec_in_year = leap_year(tmp_year) ? SECS_IN_LEAP_YEAR : SECS_IN_NON_LEAP_YEAR; + + if (tmp >= sec_in_year) { + tmp -= sec_in_year; + tmp_year++; + } else { + break; + } + } + /* Find month of year */ + while (true) { + sec_in_month = get_secs_in_month(tmp_year, tmp_month); + + if (tmp >= sec_in_month) { + tmp -= sec_in_month; + tmp_month++; + } else { + break; + } + } + /* Find day of month */ + while (true) { + if (tmp >= SECS_IN_DAY) { + tmp -= SECS_IN_DAY; + tmp_day++; + } else { + break; + } + } + /* Find hour of day */ + while (true) { + if (tmp >= SECS_IN_HOUR) { + tmp -= SECS_IN_HOUR; + tmp_hour++; + } else { + break; + } + } + /* Find minute in hour */ + while (true) { + if (tmp >= SECS_IN_MINUTE) { + tmp -= SECS_IN_MINUTE; + tmp_minutes++; + } else { + break; + } + } + + dt->date.year = tmp_year; + dt->date.month = tmp_month; + dt->date.day = tmp_day; + dt->time.hour = tmp_hour; + dt->time.min = tmp_minutes; + dt->time.sec = tmp; + + return ERR_NONE; +} + +/** \brief convert date/time to timestamp + * \return timestamp + */ +static uint32_t convert_datetime_to_timestamp(struct calendar_descriptor *const calendar, struct calendar_date_time *dt) +{ + uint32_t tmp = 0; + uint32_t i = 0; + uint8_t year, month, day, hour, minutes, seconds; + + year = dt->date.year - calendar->base_year; + month = dt->date.month; + day = dt->date.day; + hour = dt->time.hour; + minutes = dt->time.min; + seconds = dt->time.sec; + + /* tot up year field */ + for (i = 0; i < year; ++i) { + if (leap_year(calendar->base_year + i)) { + tmp += SECS_IN_LEAP_YEAR; + } else { + tmp += SECS_IN_NON_LEAP_YEAR; + } + } + + /* tot up month field */ + for (i = 1; i < month; ++i) { + tmp += get_secs_in_month(dt->date.year, i); + } + + /* tot up day/hour/minute/second fields */ + tmp += (day - 1) * SECS_IN_DAY; + tmp += hour * SECS_IN_HOUR; + tmp += minutes * SECS_IN_MINUTE; + tmp += seconds; + + return tmp; +} + +/** \brief calibrate timestamp to make desired timestamp ahead of current timestamp + */ +static void calibrate_timestamp(struct calendar_descriptor *const calendar, struct calendar_alarm *alarm, + struct calendar_alarm *current_dt) +{ + uint32_t alarm_ts; + uint32_t current_ts = current_dt->cal_alarm.timestamp; + + alarm_ts = alarm->cal_alarm.timestamp; + + /* calibrate timestamp */ + switch (alarm->cal_alarm.option) { + case CALENDAR_ALARM_MATCH_SEC: + + if (alarm_ts <= current_ts) { + alarm_ts += SECS_IN_MINUTE; + } + + break; + case CALENDAR_ALARM_MATCH_MIN: + + if (alarm_ts <= current_ts) { + alarm_ts += SECS_IN_HOUR; + } + + break; + case CALENDAR_ALARM_MATCH_HOUR: + + if (alarm_ts <= current_ts) { + alarm_ts += SECS_IN_DAY; + } + + break; + case CALENDAR_ALARM_MATCH_DAY: + + if (alarm_ts <= current_ts) { + alarm_ts += get_secs_in_month(current_dt->cal_alarm.datetime.date.year, + current_dt->cal_alarm.datetime.date.month); + } + + break; + case CALENDAR_ALARM_MATCH_MONTH: + + if (alarm_ts <= current_ts) { + if (leap_year(current_dt->cal_alarm.datetime.date.year)) { + alarm_ts += SECS_IN_LEAP_YEAR; + } else { + alarm_ts += SECS_IN_NON_LEAP_YEAR; + } + } + + break; + /* do nothing for year match */ + case CALENDAR_ALARM_MATCH_YEAR: + default: + break; + } + + /* desired timestamp after calibration */ + alarm->cal_alarm.timestamp = alarm_ts; +} + +/** \brief complete alarm to absolute date/time, then fill up the timestamp + */ +static void fill_alarm(struct calendar_descriptor *const calendar, struct calendar_alarm *alarm) +{ + struct calendar_alarm current_dt; + uint32_t tmp, current_ts; + + /* get current date/time */ + current_ts = _calendar_get_counter(&calendar->device); + convert_timestamp_to_datetime(calendar, current_ts, ¤t_dt.cal_alarm.datetime); + + current_dt.cal_alarm.timestamp = current_ts; + + /* complete alarm */ + switch (alarm->cal_alarm.option) { + case CALENDAR_ALARM_MATCH_SEC: + alarm->cal_alarm.datetime.date.year = current_dt.cal_alarm.datetime.date.year; + alarm->cal_alarm.datetime.date.month = current_dt.cal_alarm.datetime.date.month; + alarm->cal_alarm.datetime.date.day = current_dt.cal_alarm.datetime.date.day; + alarm->cal_alarm.datetime.time.hour = current_dt.cal_alarm.datetime.time.hour; + alarm->cal_alarm.datetime.time.min = current_dt.cal_alarm.datetime.time.min; + break; + case CALENDAR_ALARM_MATCH_MIN: + alarm->cal_alarm.datetime.date.year = current_dt.cal_alarm.datetime.date.year; + alarm->cal_alarm.datetime.date.month = current_dt.cal_alarm.datetime.date.month; + alarm->cal_alarm.datetime.date.day = current_dt.cal_alarm.datetime.date.day; + alarm->cal_alarm.datetime.time.hour = current_dt.cal_alarm.datetime.time.hour; + break; + case CALENDAR_ALARM_MATCH_HOUR: + alarm->cal_alarm.datetime.date.year = current_dt.cal_alarm.datetime.date.year; + alarm->cal_alarm.datetime.date.month = current_dt.cal_alarm.datetime.date.month; + alarm->cal_alarm.datetime.date.day = current_dt.cal_alarm.datetime.date.day; + break; + case CALENDAR_ALARM_MATCH_DAY: + alarm->cal_alarm.datetime.date.year = current_dt.cal_alarm.datetime.date.year; + alarm->cal_alarm.datetime.date.month = current_dt.cal_alarm.datetime.date.month; + break; + case CALENDAR_ALARM_MATCH_MONTH: + alarm->cal_alarm.datetime.date.year = current_dt.cal_alarm.datetime.date.year; + break; + case CALENDAR_ALARM_MATCH_YEAR: + break; + default: + break; + } + + /* fill up the timestamp */ + tmp = convert_datetime_to_timestamp(calendar, &alarm->cal_alarm.datetime); + alarm->cal_alarm.timestamp = tmp; + + /* calibrate the timestamp */ + calibrate_timestamp(calendar, alarm, ¤t_dt); + convert_timestamp_to_datetime(calendar, alarm->cal_alarm.timestamp, &alarm->cal_alarm.datetime); +} + +/** \brief add new alarm into the list in ascending order + */ +static int32_t calendar_add_new_alarm(struct list_descriptor *list, struct calendar_alarm *alarm) +{ + struct calendar_descriptor *calendar = CONTAINER_OF(list, struct calendar_descriptor, alarms); + struct calendar_alarm * head, *it, *prev = NULL; + + /*get the head of alarms list*/ + head = (struct calendar_alarm *)list_get_head(list); + + /*if head is null, insert new alarm as head*/ + if (!head) { + list_insert_as_head(list, alarm); + _calendar_set_comp(&calendar->device, alarm->cal_alarm.timestamp); + return ERR_NONE; + } + + /*insert the new alarm in accending order, the head will be invoked firstly */ + for (it = head; it; it = (struct calendar_alarm *)list_get_next_element(it)) { + if (alarm->cal_alarm.timestamp <= it->cal_alarm.timestamp) { + break; + } + + prev = it; + } + + /*insert new alarm into the list */ + if (it == head) { + list_insert_as_head(list, alarm); + /*get the head and set it into register*/ + _calendar_set_comp(&calendar->device, alarm->cal_alarm.timestamp); + + } else { + list_insert_after(prev, alarm); + } + + return ERR_NONE; +} + +/** \brief callback for alarm + */ +static void calendar_alarm(struct calendar_dev *const dev) +{ + struct calendar_descriptor *calendar = CONTAINER_OF(dev, struct calendar_descriptor, device); + + struct calendar_alarm *head, *it, current_dt; + + if ((calendar->flags & SET_ALARM_BUSY) || (calendar->flags & PROCESS_ALARM_BUSY)) { + calendar->flags |= PROCESS_ALARM_BUSY; + return; + } + + /* get current timestamp */ + current_dt.cal_alarm.timestamp = _calendar_get_counter(dev); + + /* get the head */ + head = (struct calendar_alarm *)list_get_head(&calendar->alarms); + ASSERT(head); + + /* remove all alarms and invoke them*/ + for (it = head; it; it = (struct calendar_alarm *)list_get_head(&calendar->alarms)) { + /* check the timestamp with current timestamp*/ + if (it->cal_alarm.timestamp <= current_dt.cal_alarm.timestamp) { + list_remove_head(&calendar->alarms); + it->callback(calendar); + + if (it->cal_alarm.mode == REPEAT) { + calibrate_timestamp(calendar, it, ¤t_dt); + convert_timestamp_to_datetime(calendar, it->cal_alarm.timestamp, &it->cal_alarm.datetime); + calendar_add_new_alarm(&calendar->alarms, it); + } + } else { + break; + } + } + + /*if no alarm in the list, register null */ + if (!it) { + _calendar_register_callback(&calendar->device, NULL); + return; + } + + /*put the new head into register */ + _calendar_set_comp(&calendar->device, it->cal_alarm.timestamp); +} + +/** \brief Initialize Calendar + */ +int32_t calendar_init(struct calendar_descriptor *const calendar, const void *hw) +{ + int32_t ret = 0; + + /* Sanity check arguments */ + ASSERT(calendar); + + if (calendar->device.hw == hw) { + /* Already initialized with current configuration */ + return ERR_NONE; + } else if (calendar->device.hw != NULL) { + /* Initialized with another configuration */ + return ERR_ALREADY_INITIALIZED; + } + calendar->device.hw = (void *)hw; + ret = _calendar_init(&calendar->device); + calendar->base_year = DEFAULT_BASE_YEAR; + + return ret; +} + +/** \brief Reset the Calendar + */ +int32_t calendar_deinit(struct calendar_descriptor *const calendar) +{ + /* Sanity check arguments */ + ASSERT(calendar); + + if (calendar->device.hw == NULL) { + return ERR_NOT_INITIALIZED; + } + _calendar_deinit(&calendar->device); + calendar->device.hw = NULL; + + return ERR_NONE; +} + +/** \brief Enable the Calendar + */ +int32_t calendar_enable(struct calendar_descriptor *const calendar) +{ + /* Sanity check arguments */ + ASSERT(calendar); + + _calendar_enable(&calendar->device); + + return ERR_NONE; +} + +/** \brief Disable the Calendar + */ +int32_t calendar_disable(struct calendar_descriptor *const calendar) +{ + /* Sanity check arguments */ + ASSERT(calendar); + + _calendar_disable(&calendar->device); + + return ERR_NONE; +} + +/** \brief Set base year for calendar + */ +int32_t calendar_set_baseyear(struct calendar_descriptor *const calendar, const uint32_t p_base_year) +{ + /* Sanity check arguments */ + ASSERT(calendar); + + calendar->base_year = p_base_year; + + return ERR_NONE; +} + +/** \brief Set time for calendar + */ +int32_t calendar_set_time(struct calendar_descriptor *const calendar, struct calendar_time *const p_calendar_time) +{ + struct calendar_date_time dt; + uint32_t current_ts, new_ts; + + /* Sanity check arguments */ + ASSERT(calendar); + + /* convert time to timestamp */ + current_ts = _calendar_get_counter(&calendar->device); + convert_timestamp_to_datetime(calendar, current_ts, &dt); + dt.time.sec = p_calendar_time->sec; + dt.time.min = p_calendar_time->min; + dt.time.hour = p_calendar_time->hour; + + new_ts = convert_datetime_to_timestamp(calendar, &dt); + + _calendar_set_counter(&calendar->device, new_ts); + + return ERR_NONE; +} + +/** \brief Set date for calendar + */ +int32_t calendar_set_date(struct calendar_descriptor *const calendar, struct calendar_date *const p_calendar_date) +{ + struct calendar_date_time dt; + uint32_t current_ts, new_ts; + + /* Sanity check arguments */ + ASSERT(calendar); + + /* convert date to timestamp */ + current_ts = _calendar_get_counter(&calendar->device); + convert_timestamp_to_datetime(calendar, current_ts, &dt); + dt.date.day = p_calendar_date->day; + dt.date.month = p_calendar_date->month; + dt.date.year = p_calendar_date->year; + + new_ts = convert_datetime_to_timestamp(calendar, &dt); + + _calendar_set_counter(&calendar->device, new_ts); + + return ERR_NONE; +} + +/** \brief Get date/time for calendar + */ +int32_t calendar_get_date_time(struct calendar_descriptor *const calendar, struct calendar_date_time *const date_time) +{ + uint32_t current_ts; + + /* Sanity check arguments */ + ASSERT(calendar); + + /* convert current timestamp to date/time */ + current_ts = _calendar_get_counter(&calendar->device); + convert_timestamp_to_datetime(calendar, current_ts, date_time); + + return ERR_NONE; +} + +/** \brief Set alarm for calendar + */ +int32_t calendar_set_alarm(struct calendar_descriptor *const calendar, struct calendar_alarm *const alarm, + calendar_cb_alarm_t callback) +{ + struct calendar_alarm *head; + + /* Sanity check arguments */ + ASSERT(calendar); + ASSERT(alarm); + + alarm->callback = callback; + + fill_alarm(calendar, alarm); + + calendar->flags |= SET_ALARM_BUSY; + + head = (struct calendar_alarm *)list_get_head(&calendar->alarms); + + if (head != NULL) { + /* already added */ + if (is_list_element(&calendar->alarms, alarm)) { + if (callback == NULL) { + /* remove alarm */ + list_delete_element(&calendar->alarms, alarm); + + if (!list_get_head(&calendar->alarms)) { + _calendar_register_callback(&calendar->device, NULL); + } + } else { + /* re-add */ + list_delete_element(&calendar->alarms, alarm); + calendar_add_new_alarm(&calendar->alarms, alarm); + } + } else if (callback != NULL) { + calendar_add_new_alarm(&calendar->alarms, alarm); + } + + calendar->flags &= ~SET_ALARM_BUSY; + + if (calendar->flags & PROCESS_ALARM_BUSY) { + CRITICAL_SECTION_ENTER() + calendar->flags &= ~PROCESS_ALARM_BUSY; + _calendar_set_irq(&calendar->device); + CRITICAL_SECTION_LEAVE() + } + } else if (callback != NULL) { + /* if head is NULL, Register callback*/ + _calendar_register_callback(&calendar->device, calendar_alarm); + calendar_add_new_alarm(&calendar->alarms, alarm); + } + + calendar->flags &= ~SET_ALARM_BUSY; + + return ERR_NONE; +} + +/** \brief Retrieve driver version + * \return Current driver version + */ +uint32_t calendar_get_version(void) +{ + return CALENDAR_VERSION; +} diff --git a/watch-library/hal/src/hal_delay.c b/watch-library/hal/src/hal_delay.c new file mode 100644 index 00000000..6f77cc70 --- /dev/null +++ b/watch-library/hal/src/hal_delay.c @@ -0,0 +1,80 @@ +/** + * \file + * + * \brief HAL delay related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include <hpl_irq.h> +#include <hpl_reset.h> +#include <hpl_sleep.h> +#include "hal_delay.h" +#include <hpl_delay.h> + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief The pointer to a hardware instance used by the driver. + */ +static void *hardware; + +/** + * \brief Initialize Delay driver + */ +void delay_init(void *const hw) +{ + _delay_init(hardware = hw); +} + +/** + * \brief Perform delay in us + */ +void delay_us(const uint16_t us) +{ + _delay_cycles(hardware, _get_cycles_for_us(us)); +} + +/** + * \brief Perform delay in ms + */ +void delay_ms(const uint16_t ms) +{ + _delay_cycles(hardware, _get_cycles_for_ms(ms)); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t delay_get_version(void) +{ + return DRIVER_VERSION; +} diff --git a/watch-library/hal/src/hal_ext_irq.c b/watch-library/hal/src/hal_ext_irq.c new file mode 100644 index 00000000..d0b92927 --- /dev/null +++ b/watch-library/hal/src/hal_ext_irq.c @@ -0,0 +1,188 @@ +/** + * \file + * + * \brief External interrupt functionality imkplementation. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_ext_irq.h" + +#define EXT_IRQ_AMOUNT 3 + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief External IRQ struct + */ +struct ext_irq { + ext_irq_cb_t cb; + uint32_t pin; +}; + +/* Remove KEIL compiling error in case no IRQ line selected */ +#if EXT_IRQ_AMOUNT == 0 +#undef EXT_IRQ_AMOUNT +#define EXT_IRQ_AMOUNT 1 +#endif + +/** + * \brief Array of external IRQs callbacks + */ +static struct ext_irq ext_irqs[EXT_IRQ_AMOUNT]; + +static void process_ext_irq(const uint32_t pin); + +/** + * \brief Initialize external irq component if any + */ +int32_t ext_irq_init(void) +{ + uint16_t i; + + for (i = 0; i < EXT_IRQ_AMOUNT; i++) { + ext_irqs[i].pin = 0xFFFFFFFF; + ext_irqs[i].cb = NULL; + } + + return _ext_irq_init(process_ext_irq); +} + +/** + * \brief Deinitialize external irq if any + */ +int32_t ext_irq_deinit(void) +{ + return _ext_irq_deinit(); +} + +/** + * \brief Register callback for the given external interrupt + */ +int32_t ext_irq_register(const uint32_t pin, ext_irq_cb_t cb) +{ + uint8_t i = 0, j = 0; + bool found = false; + + for (; i < EXT_IRQ_AMOUNT; i++) { + if (ext_irqs[i].pin == pin) { + ext_irqs[i].cb = cb; + found = true; + break; + } + } + + if (NULL == cb) { + if (!found) { + return ERR_INVALID_ARG; + } + return _ext_irq_enable(pin, false); + } + + if (!found) { + for (i = 0; i < EXT_IRQ_AMOUNT; i++) { + if (NULL == ext_irqs[i].cb) { + ext_irqs[i].cb = cb; + ext_irqs[i].pin = pin; + found = true; + break; + } + } + for (; (j < EXT_IRQ_AMOUNT) && (i < EXT_IRQ_AMOUNT); j++) { + if ((ext_irqs[i].pin < ext_irqs[j].pin) && (ext_irqs[j].pin != 0xFFFFFFFF)) { + struct ext_irq tmp = ext_irqs[j]; + + ext_irqs[j] = ext_irqs[i]; + ext_irqs[i] = tmp; + } + } + } + + if (!found) { + return ERR_INVALID_ARG; + } + + return _ext_irq_enable(pin, true); +} + +/** + * \brief Enable external irq + */ +int32_t ext_irq_enable(const uint32_t pin) +{ + return _ext_irq_enable(pin, true); +} + +/** + * \brief Disable external irq + */ +int32_t ext_irq_disable(const uint32_t pin) +{ + return _ext_irq_enable(pin, false); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t ext_irq_get_version(void) +{ + return DRIVER_VERSION; +} + +/** + * \brief Interrupt processing routine + * + * \param[in] pin The pin which triggered the interrupt + */ +static void process_ext_irq(const uint32_t pin) +{ + uint8_t lower = 0, middle, upper = EXT_IRQ_AMOUNT; + + while (upper >= lower) { + middle = (upper + lower) >> 1; + if (middle >= EXT_IRQ_AMOUNT) { + return; + } + + if (ext_irqs[middle].pin == pin) { + if (ext_irqs[middle].cb) { + ext_irqs[middle].cb(); + } + return; + } + + if (ext_irqs[middle].pin < pin) { + lower = middle + 1; + } else { + upper = middle - 1; + } + } +} diff --git a/watch-library/hal/src/hal_gpio.c b/watch-library/hal/src/hal_gpio.c new file mode 100644 index 00000000..00dfea6f --- /dev/null +++ b/watch-library/hal/src/hal_gpio.c @@ -0,0 +1,44 @@ +/** + * \file + * + * \brief Port + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_gpio.h" + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +uint32_t gpio_get_version(void) +{ + return DRIVER_VERSION; +} diff --git a/watch-library/hal/src/hal_i2c_m_sync.c b/watch-library/hal/src/hal_i2c_m_sync.c new file mode 100644 index 00000000..30821a27 --- /dev/null +++ b/watch-library/hal/src/hal_i2c_m_sync.c @@ -0,0 +1,258 @@ +/** + * \file + * + * \brief I/O I2C related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include <hal_i2c_m_sync.h> +#include <utils.h> +#include <utils_assert.h> + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Sync version of I2C I/O read + */ +static int32_t i2c_m_sync_read(struct io_descriptor *io, uint8_t *buf, const uint16_t n) +{ + struct i2c_m_sync_desc *i2c = CONTAINER_OF(io, struct i2c_m_sync_desc, io); + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = n; + msg.flags = I2C_M_STOP | I2C_M_RD; + msg.buffer = buf; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret) { + return ret; + } + + return n; +} + +/** + * \brief Sync version of I2C I/O write + */ +static int32_t i2c_m_sync_write(struct io_descriptor *io, const uint8_t *buf, const uint16_t n) +{ + struct i2c_m_sync_desc *i2c = CONTAINER_OF(io, struct i2c_m_sync_desc, io); + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = n; + msg.flags = I2C_M_STOP; + msg.buffer = (uint8_t *)buf; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret) { + return ret; + } + + return n; +} + +/** + * \brief Sync version of i2c initialize + */ +int32_t i2c_m_sync_init(struct i2c_m_sync_desc *i2c, void *hw) +{ + int32_t init_status; + ASSERT(i2c); + + init_status = _i2c_m_sync_init(&i2c->device, hw); + if (init_status) { + return init_status; + } + + /* Init I/O */ + i2c->io.read = i2c_m_sync_read; + i2c->io.write = i2c_m_sync_write; + + return ERR_NONE; +} + +/** + * \brief deinitialize + */ +int32_t i2c_m_sync_deinit(struct i2c_m_sync_desc *i2c) +{ + int32_t status; + ASSERT(i2c); + + status = _i2c_m_sync_deinit(&i2c->device); + if (status) { + return status; + } + + i2c->io.read = NULL; + i2c->io.write = NULL; + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c enable + */ +int32_t i2c_m_sync_enable(struct i2c_m_sync_desc *i2c) +{ + return _i2c_m_sync_enable(&i2c->device); +} + +/** + * \brief Sync version of i2c disable + */ +int32_t i2c_m_sync_disable(struct i2c_m_sync_desc *i2c) +{ + return _i2c_m_sync_disable(&i2c->device); +} + +/** + * \brief Sync version of i2c set slave address + */ +int32_t i2c_m_sync_set_slaveaddr(struct i2c_m_sync_desc *i2c, int16_t addr, int32_t addr_len) +{ + return i2c->slave_addr = (addr & 0x3ff) | (addr_len & I2C_M_TEN); +} + +/** + * \brief Sync version of i2c set baudrate + */ +int32_t i2c_m_sync_set_baudrate(struct i2c_m_sync_desc *i2c, uint32_t clkrate, uint32_t baudrate) +{ + return _i2c_m_sync_set_baudrate(&i2c->device, clkrate, baudrate); +} + +/** + * \brief Sync version of i2c write command + */ +int32_t i2c_m_sync_cmd_write(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length) +{ + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = 1; + msg.flags = 0; + msg.buffer = ® + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + msg.flags = I2C_M_STOP; + msg.buffer = buffer; + msg.len = length; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c read command + */ +int32_t i2c_m_sync_cmd_read(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length) +{ + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = 1; + msg.flags = 0; + msg.buffer = ® + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + msg.flags = I2C_M_STOP | I2C_M_RD; + msg.buffer = buffer; + msg.len = length; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c transfer command + */ +int32_t i2c_m_sync_transfer(struct i2c_m_sync_desc *const i2c, struct _i2c_m_msg *msg) +{ + return _i2c_m_sync_transfer(&i2c->device, msg); +} + +/** + * \brief Sync version of i2c send stop condition command + */ +int32_t i2c_m_sync_send_stop(struct i2c_m_sync_desc *const i2c) +{ + return _i2c_m_sync_send_stop(&i2c->device); +} + +/** + * \brief Retrieve I/O descriptor + */ +int32_t i2c_m_sync_get_io_descriptor(struct i2c_m_sync_desc *const i2c, struct io_descriptor **io) +{ + *io = &i2c->io; + return ERR_NONE; +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t i2c_m_sync_get_version(void) +{ + return DRIVER_VERSION; +} diff --git a/watch-library/hal/src/hal_init.c b/watch-library/hal/src/hal_init.c new file mode 100644 index 00000000..fb65341f --- /dev/null +++ b/watch-library/hal/src/hal_init.c @@ -0,0 +1,47 @@ +/** + * \file + * + * \brief HAL initialization related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_init.h" + +/** + * \brief Driver version + */ +#define HAL_INIT_VERSION 0x00000001u + +/** + * \brief Retrieve the current driver version + */ +uint32_t init_get_version(void) +{ + return HAL_INIT_VERSION; +} diff --git a/watch-library/hal/src/hal_io.c b/watch-library/hal/src/hal_io.c new file mode 100644 index 00000000..7e8feb04 --- /dev/null +++ b/watch-library/hal/src/hal_io.c @@ -0,0 +1,63 @@ +/** + * \file + * + * \brief I/O functionality implementation. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include <hal_io.h> +#include <utils_assert.h> + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +uint32_t io_get_version(void) +{ + return DRIVER_VERSION; +} + +/** + * \brief I/O write interface + */ +int32_t io_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length) +{ + ASSERT(io_descr && buf); + return io_descr->write(io_descr, buf, length); +} + +/** + * \brief I/O read interface + */ +int32_t io_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length) +{ + ASSERT(io_descr && buf); + return io_descr->read(io_descr, buf, length); +} diff --git a/watch-library/hal/src/hal_pwm.c b/watch-library/hal/src/hal_pwm.c new file mode 100644 index 00000000..bc0629fd --- /dev/null +++ b/watch-library/hal/src/hal_pwm.c @@ -0,0 +1,160 @@ +/** + * \file + * + * \brief PWM functionality implementation. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_pwm.h" +#include <utils_assert.h> +#include <utils.h> + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +static void pwm_period_expired(struct _pwm_device *device); +static void pwm_detect_fault(struct _pwm_device *device); + +/** + * \brief Initialize pwm + */ +int32_t pwm_init(struct pwm_descriptor *const descr, void *const hw, struct _pwm_hpl_interface *const func) +{ + ASSERT(descr && hw && func); + descr->func = func; + descr->func->init(&descr->device, hw); + descr->device.callback.pwm_period_cb = pwm_period_expired; + descr->device.callback.pwm_error_cb = pwm_detect_fault; + return ERR_NONE; +} + +/** + * \brief Deinitialize pwm + */ +int32_t pwm_deinit(struct pwm_descriptor *const descr) +{ + ASSERT(descr && descr->func); + descr->func->deinit(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Start pwm + */ +int32_t pwm_enable(struct pwm_descriptor *const descr) +{ + ASSERT(descr && descr->func); + if (descr->func->is_pwm_enabled(&descr->device)) { + return ERR_DENIED; + } + descr->func->start_pwm(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Stop pwm + */ +int32_t pwm_disable(struct pwm_descriptor *const descr) +{ + ASSERT(descr && descr->func); + if (!descr->func->is_pwm_enabled(&descr->device)) { + return ERR_DENIED; + } + descr->func->stop_pwm(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Register PWM callback + */ +int32_t pwm_register_callback(struct pwm_descriptor *const descr, enum pwm_callback_type type, pwm_cb_t cb) +{ + switch (type) { + case PWM_PERIOD_CB: + descr->pwm_cb.period = cb; + break; + + case PWM_ERROR_CB: + descr->pwm_cb.error = cb; + break; + + default: + return ERR_INVALID_ARG; + } + ASSERT(descr && descr->func); + descr->func->set_irq_state(&descr->device, (enum _pwm_callback_type)type, NULL != cb); + return ERR_NONE; +} + +/** + * \brief Change PWM parameter + */ +int32_t pwm_set_parameters(struct pwm_descriptor *const descr, const pwm_period_t period, const pwm_period_t duty_cycle) +{ + ASSERT(descr && descr->func); + descr->func->set_pwm_param(&descr->device, period, duty_cycle); + return ERR_NONE; +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t pwm_get_version(void) +{ + return DRIVER_VERSION; +} + +/** + * \internal Process interrupts caused by period experied + */ +static void pwm_period_expired(struct _pwm_device *device) +{ + struct pwm_descriptor *const descr = CONTAINER_OF(device, struct pwm_descriptor, device); + + if (descr->pwm_cb.period) { + descr->pwm_cb.period(descr); + } +} + +/** + * \internal Process interrupts caused by pwm fault + */ +static void pwm_detect_fault(struct _pwm_device *device) +{ + struct pwm_descriptor *const descr = CONTAINER_OF(device, struct pwm_descriptor, device); + + if (descr->pwm_cb.error) { + descr->pwm_cb.error(descr); + } +} diff --git a/watch-library/hal/src/hal_slcd_sync.c b/watch-library/hal/src/hal_slcd_sync.c new file mode 100644 index 00000000..573eb0e2 --- /dev/null +++ b/watch-library/hal/src/hal_slcd_sync.c @@ -0,0 +1,150 @@ +/** + * \file + * + * \brief SLCD Segment Liquid Crystal Display Controller(Sync) functionality + * declaration. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include <hal_slcd_sync.h> +#include <utils_assert.h> + +/** + * \brief Initialize SLCD Descriptor + */ +int32_t slcd_sync_init(struct slcd_sync_descriptor *const descr, void *const hw) +{ + ASSERT(descr && hw); + return _slcd_sync_init(&descr->dev, hw); +} + +/** + * \brief Deinitialize SLCD Descriptor + */ +int32_t slcd_sync_deinit(struct slcd_sync_descriptor *const descr) +{ + ASSERT(descr); + return _slcd_sync_deinit(&descr->dev); +} + +/** + * \brief Enable SLCD driver + * + */ +int32_t slcd_sync_enable(struct slcd_sync_descriptor *const descr) +{ + ASSERT(descr); + return _slcd_sync_enable(&descr->dev); +} +/** + * \brief Disable SLCD driver + * + */ +int32_t slcd_sync_disable(struct slcd_sync_descriptor *const descr) +{ + ASSERT(descr); + return _slcd_sync_disable(&descr->dev); +} +/** + * \brief Turn on a Segment + */ +int32_t slcd_sync_seg_on(struct slcd_sync_descriptor *const descr, uint32_t seg) +{ + ASSERT(descr); + return _slcd_sync_seg_on(&descr->dev, seg); +} +/** + * \brief Turn off a Segment + */ +int32_t slcd_sync_seg_off(struct slcd_sync_descriptor *const descr, uint32_t seg) +{ + ASSERT(descr); + return _slcd_sync_seg_off(&descr->dev, seg); +} +/** + * \brief Blink a Segment + */ +int32_t slcd_sync_seg_blink(struct slcd_sync_descriptor *const descr, uint32_t seg, const uint32_t period) +{ + ASSERT(descr && period); + return _slcd_sync_seg_blink(&descr->dev, seg, period); +} + +/** + * \brief Displays a character + */ +int32_t slcd_sync_write_char(struct slcd_sync_descriptor *const descr, const uint8_t character, uint32_t index) +{ + ASSERT(descr); + return _slcd_sync_write_char(&descr->dev, character, index); +} + +/** + * \brief Displays character string string + */ +int32_t slcd_sync_write_string(struct slcd_sync_descriptor *const descr, uint8_t *const str, uint32_t len, + uint32_t index) +{ + uint32_t i; + ASSERT(descr && len); + + for (i = 0; i < len; i++) { + if (_slcd_sync_write_char(&descr->dev, *(str + i), index + i) != ERR_NONE) { + return ERR_INVALID_ARG; + } + } + return ERR_NONE; +} +/** + * \brief Start animation play by a segment array + */ +int32_t slcd_sync_start_animation(struct slcd_sync_descriptor *const descr, const uint32_t segs[], uint32_t len, + const uint32_t period) +{ + ASSERT(descr && segs && len && period); + return _slcd_sync_start_animation(&descr->dev, segs, len, period); +} + +/** + * \brief Stop animation play by a segment array + */ +int32_t slcd_sync_stop_animation(struct slcd_sync_descriptor *const descr, const uint32_t segs[], uint32_t len) +{ + ASSERT(descr && segs && len); + return _slcd_sync_stop_animation(&descr->dev, segs, len); +} + +/** + * \brief Set animation Frequency + */ +int32_t slcd_sync_set_animation_period(struct slcd_sync_descriptor *const descr, const uint32_t period) +{ + ASSERT(descr && period); + return _slcd_sync_set_animation_period(&descr->dev, period); +} diff --git a/watch-library/hal/src/hal_sleep.c b/watch-library/hal/src/hal_sleep.c new file mode 100644 index 00000000..89472f15 --- /dev/null +++ b/watch-library/hal/src/hal_sleep.c @@ -0,0 +1,73 @@ +/** + * \file + * + * \brief Sleep related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_sleep.h" +#include <hpl_sleep.h> + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Set the sleep mode of the device and put the MCU to sleep + * + * For an overview of which systems are disabled in sleep for the different + * sleep modes, see the data sheet. + * + * \param[in] mode Sleep mode to use + * + * \return The status of a sleep request + * \retval -1 The requested sleep mode was invalid or not available + * \retval 0 The operation completed successfully, returned after leaving the + * sleep + */ +int sleep(const uint8_t mode) +{ + if (ERR_NONE != _set_sleep_mode(mode)) + return ERR_INVALID_ARG; + + _go_to_sleep(); + + return ERR_NONE; +} + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version + */ +uint32_t sleep_get_version(void) +{ + return DRIVER_VERSION; +} |