diff options
-rw-r--r-- | FT245.c | 601 | ||||
-rw-r--r-- | FT245.h | 235 | ||||
-rw-r--r-- | circular_buffer.h | 82 |
3 files changed, 918 insertions, 0 deletions
@@ -0,0 +1,601 @@ +#include "FT245.h" +#include <stdint.h> +#include <stdbool.h> +#include "circular_buffer.h" +#include <stdatomic.h> + +static void data_out(ft245_t *ft245); +static void data_in(ft245_t *ft245); +static void bit_set(ft245_t *ft245, uint8_t bit); +static void bit_reset(ft245_t *ft245, uint8_t bit); +static bool tx_word(ft245_t *ft245); +static bool rx_word(ft245_t *ft245); + +static atomic_flag lock = ATOMIC_FLAG_INIT; + +void ft245_init(ft245_t *ft245) +{ + data_in(ft245); + + cb_init(ft245->buffer_rx, FT245_BUFFER_SIZE_RX); + cb_init(ft245->buffer_tx, FT245_BUFFER_SIZE_TX); + + ft245->clk_state = false; + ft245->clk_count = 0; +} + +static void data_out(ft245_t *ft245) +{ + ft245->DATA0_to_output(); + ft245->DATA1_to_output(); + ft245->DATA2_to_output(); + ft245->DATA3_to_output(); + ft245->DATA4_to_output(); + ft245->DATA5_to_output(); + ft245->DATA6_to_output(); + ft245->DATA7_to_output(); + ft245->DATA8_to_output(); + ft245->DATA9_to_output(); + ft245->DATA10_to_output(); + ft245->DATA11_to_output(); + ft245->DATA12_to_output(); + ft245->DATA13_to_output(); + ft245->DATA14_to_output(); + ft245->DATA15_to_output(); + ft245->DATA16_to_output(); + ft245->DATA17_to_output(); + ft245->DATA18_to_output(); + ft245->DATA19_to_output(); + ft245->DATA20_to_output(); + ft245->DATA21_to_output(); + ft245->DATA22_to_output(); + ft245->DATA23_to_output(); + ft245->DATA24_to_output(); + ft245->DATA25_to_output(); + ft245->DATA26_to_output(); + ft245->DATA27_to_output(); + ft245->DATA28_to_output(); + ft245->DATA29_to_output(); + ft245->DATA30_to_output(); + ft245->DATA31_to_output(); + ft245->BE0_to_output(); + ft245->BE1_to_output(); + ft245->BE2_to_output(); + ft245->BE3_to_output(); +} + +static void data_in(ft245_t *ft245) +{ + ft245->DATA0_to_input(); + ft245->DATA1_to_input(); + ft245->DATA2_to_input(); + ft245->DATA3_to_input(); + ft245->DATA4_to_input(); + ft245->DATA5_to_input(); + ft245->DATA6_to_input(); + ft245->DATA7_to_input(); + ft245->DATA8_to_input(); + ft245->DATA9_to_input(); + ft245->DATA10_to_input(); + ft245->DATA11_to_input(); + ft245->DATA12_to_input(); + ft245->DATA13_to_input(); + ft245->DATA14_to_input(); + ft245->DATA15_to_input(); + ft245->DATA16_to_input(); + ft245->DATA17_to_input(); + ft245->DATA18_to_input(); + ft245->DATA19_to_input(); + ft245->DATA20_to_input(); + ft245->DATA21_to_input(); + ft245->DATA22_to_input(); + ft245->DATA23_to_input(); + ft245->DATA24_to_input(); + ft245->DATA25_to_input(); + ft245->DATA26_to_input(); + ft245->DATA27_to_input(); + ft245->DATA28_to_input(); + ft245->DATA29_to_input(); + ft245->DATA30_to_input(); + ft245->DATA31_to_input(); + ft245->BE0_to_input(); + ft245->BE1_to_input(); + ft245->BE2_to_input(); + ft245->BE3_to_input(); +} + +static void bit_set(ft245_t *ft245, uint8_t bit) +{ + switch(bit) { + case 0: + ft245->DATA0_set(); + break; + case 1: + ft245->DATA1_set(); + break; + case 2: + ft245->DATA2_set(); + break; + case 3: + ft245->DATA3_set(); + break; + case 4: + ft245->DATA4_set(); + break; + case 5: + ft245->DATA5_set(); + break; + case 6: + ft245->DATA6_set(); + break; + case 7: + ft245->DATA7_set(); + break; + case 8: + ft245->DATA8_set(); + break; + case 9: + ft245->DATA9_set(); + break; + case 10: + ft245->DATA10_set(); + break; + case 11: + ft245->DATA11_set(); + break; + case 12: + ft245->DATA12_set(); + break; + case 13: + ft245->DATA13_set(); + break; + case 14: + ft245->DATA14_set(); + break; + case 15: + ft245->DATA15_set(); + break; + case 16: + ft245->DATA16_set(); + break; + case 17: + ft245->DATA17_set(); + break; + case 18: + ft245->DATA18_set(); + break; + case 19: + ft245->DATA19_set(); + break; + case 20: + ft245->DATA20_set(); + break; + case 21: + ft245->DATA21_set(); + break; + case 22: + ft245->DATA22_set(); + break; + case 23: + ft245->DATA23_set(); + break; + case 24: + ft245->DATA24_set(); + break; + case 25: + ft245->DATA25_set(); + break; + case 26: + ft245->DATA26_set(); + break; + case 27: + ft245->DATA27_set(); + break; + case 28: + ft245->DATA28_set(); + break; + case 29: + ft245->DATA29_set(); + break; + case 30: + ft245->DATA30_set(); + break; + case 31: + ft245->DATA31_set(); + break; + } +} + +static void bit_reset(ft245_t *ft245, uint8_t bit) +{ + switch(bit) { + case 0: + ft245->DATA0_reset(); + break; + case 1: + ft245->DATA1_reset(); + break; + case 2: + ft245->DATA2_reset(); + break; + case 3: + ft245->DATA3_reset(); + break; + case 4: + ft245->DATA4_reset(); + break; + case 5: + ft245->DATA5_reset(); + break; + case 6: + ft245->DATA6_reset(); + break; + case 7: + ft245->DATA7_reset(); + break; + case 8: + ft245->DATA8_reset(); + break; + case 9: + ft245->DATA9_reset(); + break; + case 10: + ft245->DATA10_reset(); + break; + case 11: + ft245->DATA11_reset(); + break; + case 12: + ft245->DATA12_reset(); + break; + case 13: + ft245->DATA13_reset(); + break; + case 14: + ft245->DATA14_reset(); + break; + case 15: + ft245->DATA15_reset(); + break; + case 16: + ft245->DATA16_reset(); + break; + case 17: + ft245->DATA17_reset(); + break; + case 18: + ft245->DATA18_reset(); + break; + case 19: + ft245->DATA19_reset(); + break; + case 20: + ft245->DATA20_reset(); + break; + case 21: + ft245->DATA21_reset(); + break; + case 22: + ft245->DATA22_reset(); + break; + case 23: + ft245->DATA23_reset(); + break; + case 24: + ft245->DATA24_reset(); + break; + case 25: + ft245->DATA25_reset(); + break; + case 26: + ft245->DATA26_reset(); + break; + case 27: + ft245->DATA27_reset(); + break; + case 28: + ft245->DATA28_reset(); + break; + case 29: + ft245->DATA29_reset(); + break; + case 30: + ft245->DATA30_reset(); + break; + case 31: + ft245->DATA31_reset(); + break; + } +} + +static bool byte_enabled_get(ft245_t *ft245, uint8_t byte) +{ + switch(byte) { + case 0: + ft245->BE0_to_input(); + return (ft245->BE0_read() != 0); + case 1: + ft245->BE1_to_input(); + return (ft245->BE1_read() != 0); + case 2: + ft245->BE2_to_input(); + return (ft245->BE2_read() != 0); + case 3: + ft245->BE3_to_input(); + return (ft245->BE3_read() != 0); + } + + return false; +} + +static void byte_enabled_set(ft245_t *ft245, uint8_t byte, bool enabled) +{ + switch(byte) { + case 0: + ft245->BE0_to_output(); + if(enabled) + ft245->BE0_set(); + else + ft245->BE0_reset(); + break; + case 1: + ft245->BE1_to_output(); + if(enabled) + ft245->BE1_set(); + else + ft245->BE1_reset(); + break; + case 2: + ft245->BE2_to_output(); + if(enabled) + ft245->BE2_set(); + else + ft245->BE2_reset(); + break; + case 3: + ft245->BE3_to_output(); + if(enabled) + ft245->BE3_set(); + else + ft245->BE3_reset(); + break; + } +} + +static bool tx_word(ft245_t *ft245) +{ + if(!cb_occupation(ft245->buffer_tx)) + return false; + + if(ft245->full_word_mode && (cb_occupation(ft245->buffer_tx) < 4)) + return false; + + data_out(ft245); + + uint8_t data = 0; + uint32_t word = 0; + + for(uint8_t i = 0; i < 4; i++) { + if(cb_occupation(ft245->buffer_tx)) { + cb_pop(ft245->buffer_tx, data); + byte_enabled_set(ft245, 3 - i, true); + } else { + data = 0; + byte_enabled_set(ft245, 3 - i, false); + } + word |= ((uint32_t) data) << (i * 8); + } + + for(uint8_t i = 0; i < 32; i++) { + if((word >> i) & 0b1) + bit_set(ft245, i); + else + bit_reset(ft245, i); + } + + return true; +} + +static bool rx_word(ft245_t *ft245) +{ + data_in(ft245); + + if((cb_size(ft245->buffer_rx) - cb_occupation(ft245->buffer_rx)) < 4) + return false; + + if(ft245->full_word_mode && !(ft245->BE3_read() && ft245->BE2_read() && ft245->BE1_read() && ft245->BE0_read())) + return false; + + uint8_t data[4]; + + if(ft245->BE3_read()) { + data[3] = ((((ft245->DATA31_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 7) | + (((ft245->DATA30_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 6) | + (((ft245->DATA29_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 5) | + (((ft245->DATA28_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 4) | + (((ft245->DATA27_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 3) | + (((ft245->DATA26_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 2) | + (((ft245->DATA25_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 1) | + (((ft245->DATA24_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 0)); + cb_push(ft245->buffer_rx, data[3]); + } else { + data[3] = 0; + cb_push(ft245->buffer_rx, data[3]); + } + + if(ft245->BE2_read()) { + data[2] = ((((ft245->DATA23_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 7) | + (((ft245->DATA22_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 6) | + (((ft245->DATA21_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 5) | + (((ft245->DATA20_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 4) | + (((ft245->DATA19_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 3) | + (((ft245->DATA18_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 2) | + (((ft245->DATA17_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 1) | + (((ft245->DATA16_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 0)); + cb_push(ft245->buffer_rx, data[2]); + } else { + data[2] = 0; + cb_push(ft245->buffer_rx, data[2]); + } + + if(ft245->BE1_read()) { + data[1] = ((((ft245->DATA15_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 7) | + (((ft245->DATA14_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 6) | + (((ft245->DATA13_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 5) | + (((ft245->DATA12_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 4) | + (((ft245->DATA11_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 3) | + (((ft245->DATA10_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 2) | + (((ft245->DATA9_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 1) | + (((ft245->DATA8_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 0)); + cb_push(ft245->buffer_rx, data[1]); + } else { + data[1] = 0; + cb_push(ft245->buffer_rx, data[1]); + } + + if(ft245->BE0_read()) { + data[0] = ((((ft245->DATA7_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 7) | + (((ft245->DATA6_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 6) | + (((ft245->DATA5_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 5) | + (((ft245->DATA4_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 4) | + (((ft245->DATA3_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 3) | + (((ft245->DATA2_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 2) | + (((ft245->DATA1_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 1) | + (((ft245->DATA0_read() == 0) ? ((uint32_t) 0) : ((uint32_t) 1)) << 0)); + cb_push(ft245->buffer_rx, data[0]); + } else { + data[0] = 0; + cb_push(ft245->buffer_rx, data[0]); + } + + // Check for sync word 0x66665555 + if((data[3] == 0x55) && (data[2] == 0x55) && (data[1] == 0x66) && (data[0] == 0x66)) + cb_reset(ft245->buffer_rx); + + return true; +} + +void ft245_periodic(ft245_t *ft245) +{ + static size_t oe_n = 0; + static size_t rd_n = 0; + static size_t wr_n = 0; + static size_t rst_n = 0; + bool rxf_n = false; + bool txe_n = false; + if(ft245->clk_state) { + ft245->CLK_reset(); + ft245->clk_state = false; + } else { + ft245->CLK_set(); + ft245->clk_state = true; + + oe_n = ft245->OE_N_read() ? 0 : (oe_n + 1); + rd_n = ft245->RD_N_read() ? 0 : (rd_n + 1); + wr_n = ft245->WR_N_read() ? 0 : (wr_n + 1); + rst_n = ft245->RST_N_read() ? 0 : (rst_n + 1); + + if(rst_n) + return; + + rxf_n = (cb_occupation(ft245->buffer_tx) > (ft245->full_word_mode ? 3 : 0)); + txe_n = !cb_full(ft245->buffer_rx); + + if(rxf_n) + ft245->RXF_N_reset(); + else + ft245->RXF_N_set(); + + if(txe_n) + ft245->TXE_N_reset(); + else + ft245->TXE_N_set(); + + // OE_N low => Output Enable + // RD_N low => Read access for master + // Both required to drive data + if(rxf_n && oe_n && rd_n) { + tx_word(ft245); + } else if(txe_n && wr_n) { + rx_word(ft245); + } else { + data_in(ft245); + } + } +} + +bool ft245_write_buffered(ft245_t *ft245, uint8_t *data, size_t size) +{ + if(cb_full(ft245->buffer_tx)) + return false; + + if(cb_size(ft245->buffer_tx) - cb_occupation(ft245->buffer_tx) < size) + return false; + + for(size_t i = 0; i < size; i++) + cb_push(ft245->buffer_tx, data[i]); + + return true; +} + +bool ft245_read_buffered(ft245_t *ft245, uint8_t *data, size_t size) +{ + if(cb_occupation(ft245->buffer_rx) < size) + return false; + + for(size_t i = 0; i < size; i++) + cb_pop(ft245->buffer_rx, data[i]); + + return true; +} + +bool ft245_write_word_buffered(ft245_t *ft245, uint32_t word) +{ + while(atomic_flag_test_and_set_explicit(&lock, memory_order_acquire)); + if(cb_size(ft245->buffer_tx) - cb_occupation(ft245->buffer_tx) < 4) { + atomic_flag_clear_explicit(&lock, memory_order_release); + return false; + } + + cb_push(ft245->buffer_tx, (word >> 0) & 0xFF); + cb_push(ft245->buffer_tx, (word >> 8) & 0xFF); + cb_push(ft245->buffer_tx, (word >> 16) & 0xFF); + cb_push(ft245->buffer_tx, (word >> 24) & 0xFF); + + atomic_flag_clear_explicit(&lock, memory_order_release); + + return true; +} + +bool ft245_read_word_buffered(ft245_t *ft245, uint32_t *word) +{ + while(atomic_flag_test_and_set_explicit(&lock, memory_order_acquire)); + if(cb_occupation(ft245->buffer_rx) < 4) { + atomic_flag_clear_explicit(&lock, memory_order_release); + return false; + } + + uint8_t data = 0; + cb_pop(ft245->buffer_rx, data); + *word |= ((uint32_t) data) << 24; + cb_pop(ft245->buffer_rx, data); + *word |= ((uint32_t) data) << 16; + cb_pop(ft245->buffer_rx, data); + *word |= ((uint32_t) data) << 8; + cb_pop(ft245->buffer_rx, data); + *word |= ((uint32_t) data) << 0; + + atomic_flag_clear_explicit(&lock, memory_order_release); + + return true; +} + +size_t ft245_available_read(ft245_t *ft245) +{ + return cb_occupation(ft245->buffer_rx); +} + +size_t ft245_available_write(ft245_t *ft245) +{ + return (cb_size(ft245->buffer_tx) - cb_occupation(ft245->buffer_tx)); +}
\ No newline at end of file @@ -0,0 +1,235 @@ +#ifndef FT245_H +#define FT245_H + +#include <stdint.h> +#include <stddef.h> +#include <stdbool.h> +#include "circular_buffer.h" + +#define FT245_BUFFER_SIZE_TX 64 +#define FT245_BUFFER_SIZE_RX 64 + +typedef circular_buffer_struct(uint8_t, FT245_BUFFER_SIZE_TX) buffer_tx_t; +typedef circular_buffer_struct(uint8_t, FT245_BUFFER_SIZE_RX) buffer_rx_t; + +typedef struct ft245 { + // Options + bool full_word_mode; + // Ring buffers + buffer_tx_t buffer_tx; + buffer_rx_t buffer_rx; + // CLK state + bool clk_state; + uint8_t clk_count; + // To input + void (*const DATA0_to_input)(void); + void (*const DATA1_to_input)(void); + void (*const DATA2_to_input)(void); + void (*const DATA3_to_input)(void); + void (*const DATA4_to_input)(void); + void (*const DATA5_to_input)(void); + void (*const DATA6_to_input)(void); + void (*const DATA7_to_input)(void); + void (*const DATA8_to_input)(void); + void (*const DATA9_to_input)(void); + void (*const DATA10_to_input)(void); + void (*const DATA11_to_input)(void); + void (*const DATA12_to_input)(void); + void (*const DATA13_to_input)(void); + void (*const DATA14_to_input)(void); + void (*const DATA15_to_input)(void); + void (*const DATA16_to_input)(void); + void (*const DATA17_to_input)(void); + void (*const DATA18_to_input)(void); + void (*const DATA19_to_input)(void); + void (*const DATA20_to_input)(void); + void (*const DATA21_to_input)(void); + void (*const DATA22_to_input)(void); + void (*const DATA23_to_input)(void); + void (*const DATA24_to_input)(void); + void (*const DATA25_to_input)(void); + void (*const DATA26_to_input)(void); + void (*const DATA27_to_input)(void); + void (*const DATA28_to_input)(void); + void (*const DATA29_to_input)(void); + void (*const DATA30_to_input)(void); + void (*const DATA31_to_input)(void); + void (*const BE0_to_input)(void); + void (*const BE1_to_input)(void); + void (*const BE2_to_input)(void); + void (*const BE3_to_input)(void); + // To output + void (*const DATA0_to_output)(void); + void (*const DATA1_to_output)(void); + void (*const DATA2_to_output)(void); + void (*const DATA3_to_output)(void); + void (*const DATA4_to_output)(void); + void (*const DATA5_to_output)(void); + void (*const DATA6_to_output)(void); + void (*const DATA7_to_output)(void); + void (*const DATA8_to_output)(void); + void (*const DATA9_to_output)(void); + void (*const DATA10_to_output)(void); + void (*const DATA11_to_output)(void); + void (*const DATA12_to_output)(void); + void (*const DATA13_to_output)(void); + void (*const DATA14_to_output)(void); + void (*const DATA15_to_output)(void); + void (*const DATA16_to_output)(void); + void (*const DATA17_to_output)(void); + void (*const DATA18_to_output)(void); + void (*const DATA19_to_output)(void); + void (*const DATA20_to_output)(void); + void (*const DATA21_to_output)(void); + void (*const DATA22_to_output)(void); + void (*const DATA23_to_output)(void); + void (*const DATA24_to_output)(void); + void (*const DATA25_to_output)(void); + void (*const DATA26_to_output)(void); + void (*const DATA27_to_output)(void); + void (*const DATA28_to_output)(void); + void (*const DATA29_to_output)(void); + void (*const DATA30_to_output)(void); + void (*const DATA31_to_output)(void); + void (*const BE0_to_output)(void); + void (*const BE1_to_output)(void); + void (*const BE2_to_output)(void); + void (*const BE3_to_output)(void); + // Set + void (*const CLK_set)(void); + void (*const RXF_N_set)(void); + void (*const TXE_N_set)(void); + void (*const DATA0_set)(void); + void (*const DATA1_set)(void); + void (*const DATA2_set)(void); + void (*const DATA3_set)(void); + void (*const DATA4_set)(void); + void (*const DATA5_set)(void); + void (*const DATA6_set)(void); + void (*const DATA7_set)(void); + void (*const DATA8_set)(void); + void (*const DATA9_set)(void); + void (*const DATA10_set)(void); + void (*const DATA11_set)(void); + void (*const DATA12_set)(void); + void (*const DATA13_set)(void); + void (*const DATA14_set)(void); + void (*const DATA15_set)(void); + void (*const DATA16_set)(void); + void (*const DATA17_set)(void); + void (*const DATA18_set)(void); + void (*const DATA19_set)(void); + void (*const DATA20_set)(void); + void (*const DATA21_set)(void); + void (*const DATA22_set)(void); + void (*const DATA23_set)(void); + void (*const DATA24_set)(void); + void (*const DATA25_set)(void); + void (*const DATA26_set)(void); + void (*const DATA27_set)(void); + void (*const DATA28_set)(void); + void (*const DATA29_set)(void); + void (*const DATA30_set)(void); + void (*const DATA31_set)(void); + void (*const BE0_set)(void); + void (*const BE1_set)(void); + void (*const BE2_set)(void); + void (*const BE3_set)(void); + // Reset + void (*const CLK_reset)(void); + void (*const RXF_N_reset)(void); + void (*const TXE_N_reset)(void); + void (*const DATA0_reset)(void); + void (*const DATA1_reset)(void); + void (*const DATA2_reset)(void); + void (*const DATA3_reset)(void); + void (*const DATA4_reset)(void); + void (*const DATA5_reset)(void); + void (*const DATA6_reset)(void); + void (*const DATA7_reset)(void); + void (*const DATA8_reset)(void); + void (*const DATA9_reset)(void); + void (*const DATA10_reset)(void); + void (*const DATA11_reset)(void); + void (*const DATA12_reset)(void); + void (*const DATA13_reset)(void); + void (*const DATA14_reset)(void); + void (*const DATA15_reset)(void); + void (*const DATA16_reset)(void); + void (*const DATA17_reset)(void); + void (*const DATA18_reset)(void); + void (*const DATA19_reset)(void); + void (*const DATA20_reset)(void); + void (*const DATA21_reset)(void); + void (*const DATA22_reset)(void); + void (*const DATA23_reset)(void); + void (*const DATA24_reset)(void); + void (*const DATA25_reset)(void); + void (*const DATA26_reset)(void); + void (*const DATA27_reset)(void); + void (*const DATA28_reset)(void); + void (*const DATA29_reset)(void); + void (*const DATA30_reset)(void); + void (*const DATA31_reset)(void); + void (*const BE0_reset)(void); + void (*const BE1_reset)(void); + void (*const BE2_reset)(void); + void (*const BE3_reset)(void); + // Toggle + void (*const CLK_toggle)(void); + // Read + uint32_t (*const TXE_N_read)(void); + uint32_t (*const RXF_N_read)(void); + uint32_t (*const WR_N_read)(void); + uint32_t (*const SIWU_N_read)(void); + uint32_t (*const RD_N_read)(void); + uint32_t (*const OE_N_read)(void); + uint32_t (*const RST_N_read)(void); + uint32_t (*const DATA0_read)(void); + uint32_t (*const DATA1_read)(void); + uint32_t (*const DATA2_read)(void); + uint32_t (*const DATA3_read)(void); + uint32_t (*const DATA4_read)(void); + uint32_t (*const DATA5_read)(void); + uint32_t (*const DATA6_read)(void); + uint32_t (*const DATA7_read)(void); + uint32_t (*const DATA8_read)(void); + uint32_t (*const DATA9_read)(void); + uint32_t (*const DATA10_read)(void); + uint32_t (*const DATA11_read)(void); + uint32_t (*const DATA12_read)(void); + uint32_t (*const DATA13_read)(void); + uint32_t (*const DATA14_read)(void); + uint32_t (*const DATA15_read)(void); + uint32_t (*const DATA16_read)(void); + uint32_t (*const DATA17_read)(void); + uint32_t (*const DATA18_read)(void); + uint32_t (*const DATA19_read)(void); + uint32_t (*const DATA20_read)(void); + uint32_t (*const DATA21_read)(void); + uint32_t (*const DATA22_read)(void); + uint32_t (*const DATA23_read)(void); + uint32_t (*const DATA24_read)(void); + uint32_t (*const DATA25_read)(void); + uint32_t (*const DATA26_read)(void); + uint32_t (*const DATA27_read)(void); + uint32_t (*const DATA28_read)(void); + uint32_t (*const DATA29_read)(void); + uint32_t (*const DATA30_read)(void); + uint32_t (*const DATA31_read)(void); + uint32_t (*const BE0_read)(void); + uint32_t (*const BE1_read)(void); + uint32_t (*const BE2_read)(void); + uint32_t (*const BE3_read)(void); +} ft245_t; + +void ft245_init(ft245_t *ft245); +void ft245_periodic(ft245_t *ft245); +bool ft245_write_buffered(ft245_t *ft245, uint8_t *data, size_t size); +bool ft245_read_buffered(ft245_t *ft245, uint8_t *data, size_t size); +bool ft245_write_word_buffered(ft245_t *ft245, uint32_t word); +bool ft245_read_word_buffered(ft245_t *ft245, uint32_t *word); +size_t ft245_available_read(ft245_t *ft245); +size_t ft245_available_write(ft245_t *ft245); + +#endif
\ No newline at end of file diff --git a/circular_buffer.h b/circular_buffer.h new file mode 100644 index 0000000..a12bbbc --- /dev/null +++ b/circular_buffer.h @@ -0,0 +1,82 @@ +/* + * ------------------------------------------------------------ + * "THE BEERWARE LICENSE" (Revision 42): + * diegohamilton26@gmail.com wrote this code. As long as you retain this + * notice, you can do whatever you want with this stuff. If we + * meet someday, and you think this stuff is worth it, you can + * buy me a beer in return, + * Diego Hamilton. + * ------------------------------------------------------------ + */ + +#ifndef _CIRCULAR_BUFFER_H +#define _CIRCULAR_BUFFER_H + +#include <stddef.h> + +/* +* BUF must be a pointer of any buffer with type 'NAME' defined. +* ELEM must be a element (NOT A POINTER) of type T defined. +*/ + +#define circular_buffer_struct(T, SIZE) \ + struct { \ + size_t occup; \ + size_t size; \ + size_t head, tail; \ + T data[SIZE]; \ + } + +#define cb_init(BUF, SIZE) \ + do { \ + (BUF).size = SIZE; \ + (BUF).occup = 0; \ + (BUF).head = 0; \ + (BUF).tail = 0; \ + } while(0) + +#define cb_size(BUF) ((BUF).size) +#define cb_full(BUF) ((BUF).occup == (BUF).size) +#define cb_empty(BUF) ((BUF).occup == 0) +#define cb_occupation(BUF) ((BUF).occup) +#define cb_reset(BUF) \ + do { \ + (BUF).head = 0; \ + (BUF).tail = 0; \ + (BUF).occup = 0; \ + } while(0) + +/* TODO: replace occup by calculations w/ head and tail? */ +#define cb_push(BUF, ELEM) \ + do { \ + ((BUF).data)[(BUF).tail] = (ELEM); \ + if ((BUF).tail == cb_size(BUF) - 1) { \ + (BUF).tail = 0; \ + } else { \ + (BUF).tail = ((BUF).tail + 1); \ + } \ + if (cb_full((BUF))) { \ + if ((BUF).head == cb_size(BUF) - 1) { \ + (BUF).head = 0; \ + } else { \ + (BUF).head = ((BUF).head + 1); \ + } \ + } else { \ + (BUF).occup = (BUF).occup + 1; \ + } \ + } while(0) + +#define cb_pop(BUF, ELEM) \ + do { \ + if(!cb_empty((BUF))) { \ + (ELEM) = (BUF).data[(BUF).head]; \ + if ((BUF).head == cb_size(BUF) - 1) { \ + (BUF).head = 0; \ + } else { \ + (BUF).head = ((BUF).head + 1); \ + } \ + (BUF).occup -= 1; \ + } \ + } while(0) + +#endif |