Skip to content

Commit

Permalink
refactoring and target frequency is now settable at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
codehero committed Sep 30, 2013
1 parent 91531d0 commit 346a45a
Show file tree
Hide file tree
Showing 4 changed files with 426 additions and 89 deletions.
4 changes: 2 additions & 2 deletions Makefile
Expand Up @@ -83,8 +83,8 @@
.SILENT: .SILENT:
.PHONY: clean .PHONY: clean


host_calibrate: host_calibrate.c host_calibrate: host_calibrate.c protocol.h
$(HOST_CC) host_calibrate.c -g -o host_calibrate -lftdi $(HOST_CC) host_calibrate.c -g -o host_calibrate


clean: clean:
-$(RM) $(OBJECTS) -$(RM) $(OBJECTS)
Expand Down
310 changes: 269 additions & 41 deletions host_calibrate.c
@@ -1,96 +1,324 @@
/* License: Public domain. */ /* License: Public domain.
*
* A free product developed by analog10 (http://analog10.com)
* Check it out!
* */

#define _BSD_SOURCE
#include <endian.h>
#include <termios.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include <signal.h> #include <signal.h>
#include <ftdi.h> #include <poll.h>

#include "protocol.h"

enum {
FIVE_ONES = 0x55
,FOUR_ONES = 0x15
,THREE_ONES = 0x05
,TWO_ONES = 0x01
,ONE_ONE = 0x00
};


static int keep_running = 1; static int keep_running = 1;
void sig_handler(int signum) { void sig_handler(int signum) {
keep_running = 0; keep_running = 0;
} }


int xmit_recv(int fd, char* dest, char send){
fprintf(stderr, "TX : %02hhx\n", send);

write(fd, &send, 1);

/* Wait for ack or err. */

struct pollfd pfd;
pfd.events = POLLIN;
pfd.fd = fd;

/* Wait 500 ms for response. */
int ret = poll(&pfd, 1, 1000);
if(-1 == ret){
fprintf(stderr, "err poll: %s\n", strerror(errno));
return -1;
}

if(0 == ret){
fprintf(stderr, "timed out...\n");
return -2;
}

ret = read(fd, dest, 1);
if(-1 == ret){
fprintf(stderr, "read err: %s\n", strerror(errno));
return -1;
}

if(OUT_RX_ERR == (*dest & 0xF0)){
fprintf(stderr, "recv err: %02hhx\n", *dest);
return -3;
}

fprintf(stderr, "RX : %02hhx\n", *dest);
return 0;
}

int main(int argc, char **argv) { int main(int argc, char **argv) {
struct ftdi_context *ftdi;
int ret; int ret;
unsigned baudrate = 9600; unsigned baudrate = 9600;
uint32_t target_freq = 16000000;

if(argc < 2){
fprintf(stderr, "Usage: TTY_DEV_NODE [BAUD_RATE] [TARGET_FREQUENCY] \n");
return 1;
}


/* Get the baudrate from the command line. */ /* Get the baudrate from the command line. */
if(argc > 1){ if(argc > 2){
char* endptr; char* endptr;
baudrate = strtoul(argv[1], &endptr, 0); baudrate = strtoul(argv[2], &endptr, 0);
if(*endptr){ if(*endptr){
fprintf(stderr, "err invalid baud rate parameter\n"); fprintf(stderr, "err invalid baud rate parameter\n");
return 1; return 1;
} }
} }


if((ftdi = ftdi_new()) == 0){ if(argc > 3){
fprintf(stderr, "err ftdi_new\n"); char* endptr;
target_freq = strtoul(argv[3], &endptr, 0);
if(*endptr || !target_freq){
fprintf(stderr, "err invalid target frequency parameter\n");
return 1;
}
}

int fd = open(argv[1], O_RDWR);
struct termios ser_options;
ret = tcgetattr(fd, &ser_options);
if(ret < 0){
fprintf(stderr, "err tcgetattr: %s\n", strerror(errno));
return 1; return 1;
} }


// Select interface /* Set Baud speed. */
ftdi_set_interface(ftdi, INTERFACE_ANY); switch(baudrate){
case 50:
baudrate = B50;
break;


/* Using FT230X here, obtained from lsusb. */ case 75:
ret = ftdi_usb_open(ftdi, 0x403, 0x6015); baudrate = B75;
break;


case 110:
baudrate = B110;
break;

case 134:
baudrate = B134;
break;

case 150:
baudrate = B150;
break;

case 200:
baudrate = B200;
break;

case 300:
baudrate = B300;
break;

case 600:
baudrate = B600;
break;

case 1200:
baudrate = B1200;
break;

case 1800:
baudrate = B1800;
break;

case 2400:
baudrate = B2400;
break;

case 4800:
baudrate = B4800;
break;

case 9600:
baudrate = B9600;
break;

case 19200:
baudrate = B19200;
break;

case 38400:
baudrate = B38400;
break;

case 57600:
baudrate = B57600;
break;

case 115200:
baudrate = B115200;
break;

case 230400:
baudrate = B230400;
break;

default:
fprintf(stderr, "err bad baudrate\n");
return 1;
}

ret = cfsetispeed(&ser_options, baudrate);
if(ret < 0){
fprintf(stderr, "err cfsetispeed: %s\n", strerror(errno));
return 1;
}

ret = cfsetospeed(&ser_options, baudrate);
if(ret < 0){ if(ret < 0){
fprintf(stderr, "err opening : %i %s\n", ret, ftdi_get_error_string(ftdi)); fprintf(stderr, "err cfsetospeed: %s\n", strerror(errno));
return 1; return 1;
} }


// Set baudrate /* Setup for raw binary comms. */
ret = ftdi_set_baudrate(ftdi, baudrate); cfmakeraw(&ser_options);

/* Reset options for communications. */
ser_options.c_cflag &= ~(PARODD | PARENB | CS5 | CS6 | CS7 | CS8 | CSTOPB);

ret = tcsetattr(fd, TCSAFLUSH, &ser_options);
if(ret < 0){ if(ret < 0){
fprintf(stderr, "err set baudrate: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); fprintf(stderr, "err tcsetattr: %s\n", strerror(errno));
return 1; return 1;
} }


signal(SIGINT, sig_handler); signal(SIGINT, sig_handler);


uint8_t output = 0x55; /* Shift frequency up to its MSB.
while(keep_running){ * Reset the frequency register and assign the value. */
/* Wait for init packet. */ unsigned bits_remaining = 32;
uint8_t rx; while(!(target_freq & 0x80000000)){
ret = ftdi_read_data(ftdi, &rx, 1); target_freq <<= 1;
if(ret < 0){ --bits_remaining;
fprintf(stderr, "Read error"); }
return 1;
/* Empty RX buffer. */
{
uint8_t buffer[1024];
struct pollfd pfd;
pfd.events = POLLIN;
pfd.fd = fd;
ret = 1024;
while(1024 == ret){
ret = poll(&pfd, 1, 500);
if(-1 == ret){
fprintf(stderr, "err poll: %s\n", strerror(errno));
return -1;
}

ret = read(fd, buffer, ret);
}
if(-1 == ret){
fprintf(stderr, "err emptying buff: %s\n", strerror(errno));
return -1;
} }
}

uint8_t rx = 0;

/* Reset register. */
ret = xmit_recv(fd, &rx, FOUR_ONES);
if(ret)
return ret;
if(rx != (OUT_RX_ACK | 4)){
return -4;
}

/* Set register value. */
while(bits_remaining){
uint8_t xmit = (target_freq & 0x80000000)
? ONE_ONE : TWO_ONES;
ret = xmit_recv(fd, &rx, xmit);
if(ret)
return ret;

/* Make sure we got proper ack back. */
if((xmit == ONE_ONE) && rx != (OUT_RX_ACK | 0x1))
return -4;

if((xmit == TWO_ONES) && rx != (OUT_RX_ACK | 0x2))
return -4;

target_freq <<= 1;
--bits_remaining;
}

/* Register is set, now initiate calibration. */
ret = xmit_recv(fd, &rx, THREE_ONES);
if(ret)
return ret;
if(rx != (OUT_RX_ACK | 0x3))
return -4;


fprintf(stderr, "Got %02hhx, %i\n", rx, ret);


if(0xcc == rx){ while(keep_running){
ret = xmit_recv(fd, &rx, 0x55);
if(ret)
return ret;

if(OUT_INCREMENT == rx){
}
else if(OUT_DECREMENT == rx){
}
else if(OUT_FINISH == rx){
/* Read dco, bcs values. */ /* Read dco, bcs values. */
uint8_t vals[2]; struct {
uint32_t estimate;
uint32_t last_diff;
uint8_t dco;
uint8_t bcs;
} result;

unsigned count = 0; unsigned count = 0;
while(count < 2){ while(count < 10){
ret = ftdi_read_data(ftdi, vals + count, 2 - count); ret = read(fd, (uint8_t*)(&result) + count, sizeof(result) - count);
fprintf(stderr, "Read back %i\n", ret); fprintf(stderr, "Read back %i\n", ret);
count += ret; count += ret;
} }
fprintf(stderr, "DCO BCS1CTL\n");
printf("%02hhx %02hhx\n", vals[0], vals[1]); result.estimate = le32toh(result.estimate);
fprintf(stderr, "DCO BCS1CTL ESTIMATE ERROR\n");
printf("%02hhx %02hhx %8u %8u\n"
,result.dco ,result.bcs ,result.estimate ,result.last_diff);
break;
}
else{
fprintf(stderr, "BAD RX %02hhx\n", rx);
break; break;
} }


usleep(100); usleep(100);

/* Write */
ret = ftdi_write_data(ftdi, &output, 1);
if(ret < 0){
fprintf(stderr, "Write error");
return 1;
}
} }


signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);


ftdi_usb_close(ftdi);
do_deinit:
ftdi_free(ftdi);

return 0; return 0;
} }

0 comments on commit 346a45a

Please sign in to comment.