#ifndef INTERFACE_H
#define INTERFACE_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>

#include "symbols_peripherals.h"

#if defined(PC)
#include "pc.h"
#elif defined(ARDUINO)
#include "arduino.h"
#else
#warning "No architecture could be detected"
#include "pc.h"
#endif

#if APINS > 255
#error "Maximum number of analog pins is 255"
#endif

#if DPINS > 255
#error "Maximum number of digital pins is 255"
#endif

#if MEMSIZE > UINT16_MAX - 3
#error "Maximum number of memory is 2^16-3"
#endif

#define read16bit() 256*(uint8_t)read_byte() + (uint8_t)read_byte()
#define write16bit(i) {                 \
	write_byte((uint8_t)((i)/256)); \
	write_byte((uint8_t)((i)%256)); \
}

/* Communication */
bool input_available(void);
uint8_t read_byte(void);
void write_byte(uint8_t b);

/* Analog and digital pins */
#if DPINS > 0 || APINS > 0
void write_dpin(uint16_t i, bool b);
bool read_dpin(uint16_t i);
void set_pinmode(uint16_t p, uint8_t mode);
uint16_t translate_pin(uint16_t pin);
#endif

#if APINS > 0
void write_apin(uint16_t i, uint8_t a);
uint8_t read_apin(uint16_t i);
#endif

#ifdef HAVE_DHT
void *dht_init(struct mt_DHTInfo);
float get_dht_temp(void *);
float get_dht_humidity(void *);
#endif

#ifdef HAVE_LEDMATRIX
void *ledmatrix_init(struct mt_LEDMatrixInfo);
void ledmatrix_dot(void *, uint8_t, uint8_t, bool);
void ledmatrix_intensity(void *, uint8_t);
void ledmatrix_clear(void *);
void ledmatrix_display(void *);
#endif

#ifdef HAVE_I2CBUTTON
void *i2c_init(uint8_t addr);
uint8_t i2c_abutton(void *);
uint8_t i2c_bbutton(void *);
#endif

#ifdef HAVE_LIGHTSENSOR
void *lightsensor_init(uint8_t addr);
float get_light(void *);
#endif

#ifdef HAVE_AIRQUALITYSENSOR
void *airqualitysensor_init(uint8_t addr);
void set_environmental_data(void *, float, float);
uint16_t get_tvoc(void *);
uint16_t get_co2(void *);
#endif

/* Delay and communication */
uint64_t getmillis(void);
void msdelay(unsigned long ms);

/* Auxilliary */
void real_setup(void);

/* Yield function to feed the dogs */
void real_yield(void);

/* Log level: debug */
#if LOGLEVEL == 2
void msg_log(const char *, ...);
#define msg_debug(...) msg_log(__VA_ARGS__)
void dump_stack(uint8_t *program, uint16_t pc, uint16_t *stack, uint16_t sp,
	uint16_t fp);

/* Log level: normal */
#elif LOGLEVEL == 1
void msg_log(const char *, ...);
#define msg_debug(...);
#define dump_stack(a, b, c, d, e);

/* Log level: quiet */
#else
#define msg_debug(...) ;
#define msg_log(...) ;
#define dump_stack(a, b, c, d, e);
#endif

void die(const char *, ...);

void pdie(char *s);
void reset(void);

#ifndef RECOVERABLE_ERROR_CODE
#define RECOVERABLE_ERROR_CODE
#endif

#ifdef __cplusplus
}

#endif
#endif
