diff options
Diffstat (limited to 'old/ft232r/soft_uart.c')
-rw-r--r-- | old/ft232r/soft_uart.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/old/ft232r/soft_uart.c b/old/ft232r/soft_uart.c new file mode 100644 index 0000000..7993036 --- /dev/null +++ b/old/ft232r/soft_uart.c @@ -0,0 +1,122 @@ + +#include <stdint.h> +#include <stdio.h> +#include <sys/types.h> + +#include "soft_uart.h" + +static inline uint32_t samples_per_etu(struct suart_data *su) +{ + return su->samplerate / su->recip_etu; +} + +static const char *state_strings[] = { + [WAIT_RESET] = "WAIT_RESET", + [IN_RESET] = "IN_RESET", + [WAIT_START_FALLEDGE] = "WAIT_START_FALLEDGE", + [WAIT_START_ETU07] = "WAIT_START_ETU07", + [RX_BITS] = "RX_BITS", + [POST_RX_WAIT_HIGH] = "POST_RX_WAIT_HIGH", +}; + +static void change_state(struct suart_data *su, enum suart_state new_state) +{ + printf("State change: %s -> %s\n", state_strings[su->state], state_strings[new_state]); + su->state = new_state; +} + +/* According to ISO/IEC 7816-3 Section 6.1.2 */ +int suart_process_sample_bit(struct suart_data *suart, uint8_t clk_bit, uint8_t rst_bit, uint8_t sample_bit) +{ + uint32_t samp_per_etu = samples_per_etu(suart); + uint8_t next_bit; + + if (rst_bit == 0 && suart->state != IN_RESET) { + change_state(suart, IN_RESET); + /* FIXME: reset some other things? */ + } + + switch (suart->state) { + case WAIT_RESET: + if (rst_bit == 0) + change_state(suart, IN_RESET); + break; + case IN_RESET: + if (rst_bit == 1) + change_state(suart, WAIT_START_FALLEDGE); + break; + case WAIT_START_FALLEDGE: + if (sample_bit == 0) { + suart->sample_after_sbit = 0; + suart->bits_pending = suart->num_bits + 1; + change_state(suart, WAIT_START_ETU07); + } + break; + case WAIT_START_ETU07: + if (suart->sample_after_sbit > (samp_per_etu/2)+1) { + if (sample_bit != 0) { + printf("!!!!!!!!!!!!!!!!!!!!! start bit after 0.7 * ETU no longer low\n"); + } else { + change_state(suart, RX_BITS); + suart->rx_char = 0; + } + } + /* else stay in this state until the condition is true */ + break; + case RX_BITS: + next_bit = suart->num_bits+1 - suart->bits_pending; +#if 0 + printf("\tRX_BITS: IO = %u, next_bit = %u, sample_after_sbit = %u, samp_per_etu = %u, required_after_sbit = %u\n", + sample_bit, next_bit, suart->sample_after_sbit, samp_per_etu, + (samp_per_etu/2) + ((next_bit+1) * samp_per_etu)); +#endif + if (suart->sample_after_sbit > (samp_per_etu/2) + ((next_bit+1) * samp_per_etu)) { + /* check if this is the parity bit */ + //printf("new_bit = %u\n", sample_bit); + if (next_bit == suart->num_bits) { + /* FIXME calculate parity */ + } else { + /* an actual data bit */ + /* Section 6.1.4.1 */ + if (suart->convention == INVERSE_CONVENTION) { + if (sample_bit == 1) + sample_bit = 0x00; + else + sample_bit = 0x80; + /* shift existing patter one to the right */ + suart->rx_char = suart->rx_char >> 1; + /* mask in the additional bit */ + suart->rx_char |= sample_bit; + } else { + suart->rx_char |= (sample_bit << next_bit); + } + } + suart->bits_pending--; + } + + if (suart->bits_pending == 0) { + + /* output the character that we decoded */ + printf("Output Byte: %02x\n", suart->rx_char); + + change_state(suart, POST_RX_WAIT_HIGH); + } + break; + case POST_RX_WAIT_HIGH: + if (sample_bit == 0x01) { + /* return to initial state */ + change_state(suart, WAIT_START_FALLEDGE); + } + break; + } + suart->sample_after_sbit++; +} + +void suart_init(struct suart_data *su) +{ + su->state = WAIT_RESET; + su->convention = DIRECT_CONVENTION; + printf("Samplerate = %u\n", su->samplerate); + printf("etu = 1 / %u\n", su->recip_etu); + printf("samp_per_etu = %u\n", samples_per_etu(su)); +} |