#pragma once #include #include #include #include "systick.h" #include "Scheduler.h" #include "timer.h" //#define SI2C_DEBUG 1 //#define SI2C_PROF 1 class Soft_I2C { public: typedef enum STATE { START, // address A_0L, A_0H, A_1L, A_1H, A_2L, A_2H, A_3L, A_3H, A_4L, A_4H, A_5L, A_5H, A_6L, A_6H, A_7L, A_7H, A_AL, A_AH, // byte write W_0L, W_0H, W_1L, W_1H, W_2L, W_2H, W_3L, W_3H, W_4L, W_4H, W_5L, W_5H, W_6L, W_6H, W_7L, W_7H, W_AL, W_AH, STOP, STOP2, RESTART, RESTART2, // 2nd stage DUMMY, // byte read after restart R_0L, R_0H, R_1L, R_1H, R_2L, R_2H, R_3L, R_3H, R_4L, R_4H, R_5L, R_5H, R_6L, R_6H, R_7L, R_7H, R_AL, R_AH, } State; #ifdef SI2C_DEBUG typedef struct SI2C_STATE { uint32_t time; State state; unsigned int sda; unsigned int f_sda; } SI2C_State; #endif Soft_I2C(); void init(); void init_hw( const gpio_dev *scl_dev, uint8_t scl_bit, const gpio_dev *sda_dev, uint8_t sda_bit, const timer_dev *tim); uint8_t writeBuffer( uint8_t addr_, uint8_t len_, const uint8_t *data); uint8_t read( uint8_t addr_, uint8_t reg, uint8_t len, uint8_t* buf); uint8_t transfer(uint8_t addr, uint8_t send_len, const uint8_t *send, uint8_t len, uint8_t *buf); bool bus_reset(void); void set_low_speed(bool s) { } private: void tick(); // ISR bool _start(void); uint8_t wait_done(); const gpio_dev *_scl_dev; uint8_t _scl_bit; const gpio_dev *_sda_dev; uint8_t _sda_bit; const timer_dev * _timer; volatile GPIO_TypeDef *scl_port; // for quick direct access to hardware uint16_t scl_pin; volatile GPIO_TypeDef *sda_port; uint16_t sda_pin; volatile bool done; volatile uint8_t result; volatile State state; bool f_sda; // what line we touch bool wait_scl; // flag - we wait for SCL stretching bool was_restart; uint8_t data; // data byte to output / from input const uint8_t *send; uint8_t send_len; uint8_t *recv; uint8_t recv_len; uint8_t _addr; uint16_t bit_time; #ifdef SI2C_DEBUG #define SI2C_LOG_SIZE 199 static SI2C_State log[SI2C_LOG_SIZE]; static uint16_t log_ptr; #endif #ifdef SI2C_PROF static uint64_t full_time; static uint32_t int_count; #endif };