stmbl/shared/hal.h

317 lines
7.5 KiB
C

/*
* This file is part of the stmbl project.
*
* Copyright (C) 2013-2015 Rene Hopf <renehopf@mac.com>
* Copyright (C) 2013-2015 Nico Stute <crinq@crinq.de>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#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;\
})