simtrace/old/ft232r/soft_uart.c

123 lines
3.3 KiB
C

#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));
}