/* * This file is part of the stmbl project. * * Copyright (C) 2013-2015 Rene Hopf * Copyright (C) 2013-2015 Nico Stute * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include #include #define MAX_HAL_PINS 800 #define HAL_NAME_LENGTH 32 #define MAX_COMP_TYPES 64 #define MAX_COMPS 64 typedef char hal_name_t[HAL_NAME_LENGTH]; typedef struct hal_pin_t{ hal_name_t name; volatile float value; struct hal_pin_t* source; } hal_pin_t; typedef struct{ hal_name_t name; void (*rt_init)(); void (*rt_deinit)(); void (*nrt_init)(); void (*rt)(float period); void (*frt)(float period); void (*nrt)(float period); int hal_pin_start_index; int hal_pin_count; uint32_t instance; } hal_comp_t; typedef struct{ hal_name_t comp_types[MAX_COMP_TYPES]; int comp_types_counter[MAX_COMP_TYPES]; int comp_type_count; int comp_type; hal_name_t tmp; hal_comp_t* hal_comps[MAX_COMPS]; int comp_count; void (*rt_init[MAX_COMPS])(); int rt_init_func_count; void (*rt_deinit[MAX_COMPS])(); int rt_deinit_func_count; void (*nrt_init[MAX_COMPS])(); int nrt_init_func_count; void (*rt[MAX_COMPS])(float period); int rt_func_count; void (*nrt[MAX_COMPS])(float period); int nrt_func_count; void (*frt[MAX_COMPS])(float period); int frt_func_count; hal_pin_t* hal_pins[MAX_HAL_PINS]; int hal_pin_count; volatile enum{ RT_CALC, RT_SLEEP, RT_STOP } rt_state; volatile enum{ FRT_CALC, FRT_SLEEP, FRT_STOP } frt_state; volatile enum { FRT_TOO_LONG, RT_TOO_LONG, MISC_ERROR, MEM_ERROR, CONFIG_LOAD_ERROR, CONFIG_ERROR, NAN_ERROR, HAL2_OK } hal_state; volatile int active_rt_func; volatile int active_frt_func; volatile int active_nrt_func; uint32_t link_errors; uint32_t pin_errors; uint32_t set_errors; uint32_t get_errors; uint32_t comp_errors; char error_name[HAL_NAME_LENGTH]; } hal_struct_t; extern hal_struct_t hal; void hal_init(); uint32_t get_fpscr(); void set_fpscr(uint32_t fpscr); void hal_comp_init(); void hal_run_rt(float period); void hal_run_nrt(float period); void hal_run_frt(float period); void hal_start(); void hal_stop(); int hal_start_rt(); int hal_start_frt(); void hal_stop_rt(); void hal_stop_frt(); void hal_init_pin(hal_name_t name, hal_pin_t* pin, float value); int hal_register_pin(hal_pin_t* pin); int hal_set_comp_type(hal_name_t name); int hal_set_pin(hal_name_t name, float value); int hal_is_pin(hal_name_t name); int hal_is_compname(hal_name_t name); float hal_get_pin(hal_name_t name); hal_pin_t hal_map_pin(hal_name_t name); void hal_write_pin(hal_pin_t* pin, float value); float hal_read_pin(hal_pin_t* pin); struct hal_pin_t* hal_find_pin(hal_name_t name); int hal_link_pins(hal_name_t source, hal_name_t sink); void hal_add_comp(hal_comp_t* comp); int32_t find_comp_by_func(uint32_t p); extern void hal_enable_rt(); extern void hal_enable_frt(); extern void hal_disable_rt(); extern void hal_disable_frt(); extern uint32_t hal_get_systick_value(); extern uint32_t hal_get_systick_reload(); extern uint32_t hal_get_systick_freq(); char* hal_itoa(int i); #define HAL_COMP(type) \ { \ static hal_comp_t self; \ strncpy(self.name, #type, HAL_NAME_LENGTH); \ self.nrt_init = 0; \ self.rt_init = 0; \ self.rt_deinit = 0; \ self.rt = 0; \ self.frt = 0; \ self.nrt = 0; \ self.hal_pin_start_index = hal.hal_pin_count; \ self.hal_pin_count = 0; \ hal_set_comp_type(self.name); \ HAL_PIN(rt_calc_time) = 0.0; \ HAL_PIN(frt_calc_time) = 0.0; \ HAL_PIN(rt_prio) = -1.0; \ HAL_PIN(frt_prio) = -1.0; #define HAL_PIN(name) \ static hal_pin_t name##_hal_pin; \ hal_init_pin(#name, &name##_hal_pin, 0.0); \ (name##_hal_pin.value) //TODO: clamp loads of stuff, like count... check length... //TODO: more than 10 pins requires fixing hal_itoa #define HAL_PIN_ARRAY(name,count) \ STATIC_ASSERT(count <= 10); \ static hal_pin_t name##_hal_pin[count]; \ for(uint32_t i = 0; i < count; i++){ \ char pinname[HAL_NAME_LENGTH]; \ strncpy(pinname,#name,HAL_NAME_LENGTH); \ strncat(pinname,hal_itoa(i),HAL_NAME_LENGTH); \ hal_init_pin(pinname, &name##_hal_pin[i], 0.0); \ } #define GLOBAL_HAL_PIN(name) \ volatile hal_pin_t name##_hal_pin; #define MEM(var) static var #define PIN(name) \ (name##_hal_pin.source->source->value) #define PIN_ARRAY(name,index) \ (name##_hal_pin[index].source->source->value) #define INIT(func) \ self.nrt_init = ({ void function(){func} function;}); #define RT_INIT(func) \ self.rt_init = ({ void function(){func} function;}); #define RT_DEINIT(func) \ self.rt_deinit = ({ void function(){func} function;}); #define RT(func) \ self.rt = ({ void function(float period){ \ uint32_t __start_time__ = hal_get_systick_value(); \ func \ uint32_t __end_time__ = hal_get_systick_value(); \ if(__start_time__ < __end_time__){ \ __start_time__ += hal_get_systick_reload(); \ } \ PIN(rt_calc_time) = ((float)(__start_time__ - __end_time__)) / hal_get_systick_freq(); \ } function;}); #define FRT(func) \ self.frt = ({ void function(float period){ \ uint32_t __start_time__ = hal_get_systick_value(); \ func \ uint32_t __end_time__ = hal_get_systick_value(); \ if(__start_time__ < __end_time__){ \ __start_time__ += hal_get_systick_reload(); \ } \ PIN(frt_calc_time) = ((float)(__start_time__ - __end_time__)) / hal_get_systick_freq(); \ } function;}); #define NRT(func) \ self.nrt = ({ void function(float period){func} function;}); #define HT(ht_code) \ { \ inline void ht_function(){ \ static float ht_time_count; \ (void) ht_time_count; \ static int jump_label_pointer = -__COUNTER__ - 2; \ static int jump_label_pointer_old = 0; \ (void) jump_label_pointer_old; \ switch(jump_label_pointer){ \ case -__COUNTER__ - 1:; \ ht_code; \ default: \ goto jump_label_ht_end; \ jump_label_ht_end: \ break; \ }\ }\ ht_function(); \ } #define GOTO(ht_label) \ jump_label_pointer = (ht_label); \ break; #define NEXT(ht_label) \ jump_label_pointer = (ht_label); #define STATE(ht_state) \ break; \ case (ht_state): #define SLEEP(time) \ ht_time_count = 0.0; \ jump_label_pointer_old = jump_label_pointer; \ case -__COUNTER__ - 2:; jump_label_pointer = -__COUNTER__ - 1; \ if(ht_time_count < (time)){ \ ht_time_count += period; \ goto jump_label_ht_end; \ } \ jump_label_pointer = jump_label_pointer_old; //TODO: rename HAL_ENDCOMP #define ENDCOMP \ self.hal_pin_count = hal.hal_pin_count - self.hal_pin_start_index; \ hal_add_comp(&self); \ } #define BLINK(N) \ ({ \ int t = (systime / 300) % (2 * N + 2); \ if(t < 2){ \ t = 0; \ } \ else{ \ t = t % 2; \ } \ t;\ })