From d5744a7d1a9f91cfe481300480dad1050585e66b Mon Sep 17 00:00:00 2001 From: ole00 Date: Sun, 24 Mar 2019 00:08:17 +0000 Subject: [PATCH] version 0.2 * added support for Win32/64 builds * fixed Mac OSX serial connection parameters --- afterburner.c | 64 +++++++----------- compile_win32.sh | 4 ++ compile_win64.sh | 4 ++ serial_port.h | 170 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 41 deletions(-) create mode 100755 compile_win32.sh create mode 100755 compile_win64.sh create mode 100644 serial_port.h diff --git a/afterburner.c b/afterburner.c index 37a319e..2fdd2c5 100644 --- a/afterburner.c +++ b/afterburner.c @@ -30,6 +30,9 @@ Requires: Changelog: * 2019.02.02 - initial version 0.1 +* 2019.03.24 - version 0.2 + - added support for Win32 and Win64 builds + - fixed serial port setup for Mac OSX This is the PC part that communicates with Arduino UNO by serial line. To compile: gcc -g3 -O0 afterburner afterburner.c @@ -40,14 +43,12 @@ To compile: gcc -g3 -O0 afterburner afterburner.c #include #include #include -#include -#include #include -#include +#include "serial_port.h" + +#define VERSION "v.0.2" -#define VERSION "v.0.1" -#define DEFAULT_DEVICE_NAME "/dev/ttyUSB0" #define MAX_LINE 200 @@ -98,7 +99,7 @@ char verbose = 0; char* filename = 0; char* deviceName = 0; -int serialF = -1; +SerialDeviceHandle serialF = INVALID_HANDLE; Galtype gal; int security = 0; unsigned short checksum; @@ -131,7 +132,7 @@ static void printHelp() { printf(" -v : verbose mode\n"); printf(" -t : the GAL type. use GAL16V8 GAL20V8 GAL22V10 ATF16V8B ATF22V10B ATF22V10C\n"); printf(" -f : JEDEC fuse map file\n"); - printf(" -d : name of the serial device. Default is: %s\n", DEFAULT_DEVICE_NAME); + printf(" -d : name of the serial device. Default is: %s\n", DEFAULT_SERIAL_DEVICE_NAME); printf(" serial params are: 38400, 8N1\n"); printf("examples:\n"); printf(" afterburner i : reads and prints the device info\n"); @@ -462,48 +463,29 @@ static char readJedec(void) { static int openSerial(void) { char buf[512]; - char devName[16]; + char devName[256] = {0}; int total; int labelPos; //open device name - snprintf(devName, 15, "%s", (deviceName == 0) ? DEFAULT_DEVICE_NAME : deviceName); - devName[15] = 0; + snprintf(devName, sizeof(devName), "%s", (deviceName == 0) ? DEFAULT_SERIAL_DEVICE_NAME : deviceName); + serialDeviceCheckName(devName, sizeof(devName)); if (verbose) { printf("opening serial: %s\n", devName); } - serialF = open(devName, O_RDWR | O_NOCTTY | O_NONBLOCK); - if (serialF < 1) { + serialF = serialDeviceOpen(devName); + if (serialF == INVALID_HANDLE) { printf("Error: failed to open serial device: %s\n", devName); return -2; } - //set the serial port parameters - { - struct termios serial; - - memset(&serial, 0, sizeof(struct termios)); - cfsetispeed(&serial, B38400); - cfsetospeed(&serial, B38400); - - serial.c_cflag |= CS8; // no parity, 1 stop bit - - if (0 != tcsetattr(serialF, TCSANOW, &serial)) { - printf("Error: failed to set serial parameters %i, %s\n", errno, strerror(errno)); - return -3; - } - } - - //ensure no leftover bytes exist on the serial line - tcdrain(serialF); - tcflush(serialF, TCIOFLUSH); //flush both queues // prod the programmer to output it's identification sprintf(buf, "*\r"); - write(serialF, buf, 2); + serialDeviceWrite(serialF, buf, 2); //read programmer's message total = waitForSerialPrompt(buf, 512, 3000); @@ -519,17 +501,17 @@ static int openSerial(void) { if (verbose) { printf("Output from programmer not recognised: %s\n", buf); } - close(serialF); - serialF = 0; + serialDeviceClose(serialF); + serialF = INVALID_HANDLE; return -4; } static void closeSerial(void) { - if (0 == serialF) { + if (INVALID_HANDLE == serialF) { return; } - close(serialF); - serialF = 0; + serialDeviceClose(serialF); + serialF = INVALID_HANDLE; } @@ -583,7 +565,7 @@ static int waitForSerialPrompt(char* buf, int bufSize, int maxDelay) { memset(buf, 0, bufSize); while (maxDelay > 0) { - readSize = read(serialF, buf, bufSize); + readSize = serialDeviceRead(serialF, buf, bufSize); if (readSize > 0) { bufPos += readSize; if (checkPromptExists(bufStart, bufTotal) >= 0) { @@ -606,7 +588,7 @@ static int sendLine(char* buf, int bufSize, int maxDelay) { int writeSize; char* obuf = buf; - if (serialF == 0) { + if (serialF == INVALID_HANDLE) { return -1; } @@ -618,9 +600,9 @@ static int sendLine(char* buf, int bufSize, int maxDelay) { // write the query into the modem's file // file is opened non blocking so we have to ensure all contents is written while (total > 0) { - writeSize = write(serialF, buf, total); + writeSize = serialDeviceWrite(serialF, buf, total); if (writeSize < 0) { - printf("ERROR: written: %i", writeSize); + printf("ERROR: written: %i (%s)\n", writeSize, strerror(errno)); return -4; } buf += writeSize; diff --git a/compile_win32.sh b/compile_win32.sh new file mode 100755 index 0000000..d078b44 --- /dev/null +++ b/compile_win32.sh @@ -0,0 +1,4 @@ +# path to your win32 cross-compiler +CC=~/opt/mingw32/bin/i686-w64-mingw32-gcc + +$CC -g3 -O0 -o afterburner_w32.exe afterburner.c -D_USE_WIN_API_ diff --git a/compile_win64.sh b/compile_win64.sh new file mode 100755 index 0000000..e562220 --- /dev/null +++ b/compile_win64.sh @@ -0,0 +1,4 @@ +# path to your Win64 cross-compiler +CC=~/opt/mingw64/bin/x86_64-w64-mingw32-gcc + +$CC -g3 -O0 -o afterburner_w64.exe afterburner.c -D_USE_WIN_API_ diff --git a/serial_port.h b/serial_port.h new file mode 100644 index 0000000..4ee8358 --- /dev/null +++ b/serial_port.h @@ -0,0 +1,170 @@ +#ifndef _SERIAL_PORT_H_ +#define _SERIAL_PORT_H_ + + +#ifdef _USE_WIN_API_ + +#include + +#define SerialDeviceHandle HANDLE +#define DEFAULT_SERIAL_DEVICE_NAME "COM1" +#define INVALID_HANDLE INVALID_HANDLE_VALUE + +// https://www.xanthium.in/Serial-Port-Programming-using-Win32-API + +static inline SerialDeviceHandle serialDeviceOpen(char* deviceName) { + SerialDeviceHandle h; + + h = CreateFile( + deviceName, //port name + GENERIC_READ | GENERIC_WRITE, //Read/Write + 0, // No Sharing + NULL, // No Security + OPEN_EXISTING,// Open existing port only + 0, // Non Overlapped I/O + NULL); // Null for Comm Devices + + if (h != INVALID_HANDLE) { + BOOL result; + COMMTIMEOUTS timeouts = { 0 }; + + DCB dcbSerialParams = { 0 }; // Initializing DCB structure + dcbSerialParams.DCBlength = sizeof(dcbSerialParams); + + result = GetCommState(h, &dcbSerialParams); + + if (!result) { + return INVALID_HANDLE; + } + + dcbSerialParams.BaudRate = CBR_38400; // Setting BaudRate = 38400 + dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8 + dcbSerialParams.StopBits = ONESTOPBIT;// Setting StopBits = 1 + dcbSerialParams.Parity = NOPARITY; // Setting Parity = None + + result = SetCommState(h, &dcbSerialParams); + if (!result) { + return INVALID_HANDLE; + } + + timeouts.ReadIntervalTimeout = 50; // in milliseconds + timeouts.ReadTotalTimeoutConstant = 50; // in milliseconds + timeouts.ReadTotalTimeoutMultiplier = 10; // in milliseconds + timeouts.WriteTotalTimeoutConstant = 50; // in milliseconds + timeouts.WriteTotalTimeoutMultiplier = 10; // in milliseconds + + result = SetCommTimeouts(h, &timeouts); + if (!result) { + return INVALID_HANDLE; + } + + return h; + } else { + return INVALID_HANDLE; + } + +} + +void serialDeviceCheckName(char* name, int maxSize) { + int nameLen = strlen(name); + //convert comxx to COMxx + if (strncmp(name, "com", 3) == 0 && (nameLen > 3 && name[3] >= '0' && name[3] <= '9')) { + name[0] = 'C'; + name[1] = 'O'; + name[2] = 'M'; + } + + // convert COMxx and higher to \\\\.\\COMxx + if (strncmp(name, "COM", 3) == 0 && (nameLen > 4 && name[3] >= '0' && name[3] <= '9')) { + if (nameLen + 4 < maxSize) { + int i; + for (i = nameLen - 1; i >= 0; i--) { + name[ i + 4] = name[i]; + } + name[0] = '\\'; + name[1] = '\\'; + name[2] = '.'; + name[3] = '\\'; + } + } +} + +static inline void serialDeviceClose(SerialDeviceHandle deviceHandle) { + CloseHandle(deviceHandle); +} + +static inline int serialDeviceWrite(SerialDeviceHandle deviceHandle, char* buffer, int bytesToWrite) { + DWORD written = 0; + WriteFile(deviceHandle, buffer, bytesToWrite, &written, NULL); + return (int) written; +} + +static inline int serialDeviceRead(SerialDeviceHandle deviceHandle, char* buffer, int bytesToRead) { + DWORD read = 0; + ReadFile(deviceHandle, buffer, bytesToRead, &read, NULL); + return (int) read; +} + +#else + +#include +#include +#include + +#include + +#define SerialDeviceHandle int +#define DEFAULT_SERIAL_DEVICE_NAME "/dev/ttyUSB0" + +#define INVALID_HANDLE -1 + +static inline SerialDeviceHandle serialDeviceOpen(char* deviceName) { + + SerialDeviceHandle h; + h = open(deviceName, O_RDWR | O_NOCTTY | O_NONBLOCK); + + if (h != INVALID_HANDLE) { + //set the serial port parameters + struct termios serial; + + memset(&serial, 0, sizeof(struct termios)); + cfsetispeed(&serial, B38400); + cfsetospeed(&serial, B38400); + + serial.c_cflag |= CS8; // no parity, 1 stop bit + serial.c_cflag |= CREAD | CLOCAL; + + if (0 != tcsetattr(h, TCSANOW, &serial)) { + close(h); + printf("Error: failed to set serial parameters %i, %s\n", errno, strerror(errno)); + return INVALID_HANDLE; + } + + //ensure no leftover bytes exist on the serial line + tcdrain(h); + tcflush(h, TCIOFLUSH); //flush both queues + return h; + } else { + return INVALID_HANDLE; + } +} + +void serialDeviceCheckName(char* name, int maxSize) { + //nothing to check +} + +static inline void serialDeviceClose(SerialDeviceHandle deviceHandle) { + close(deviceHandle); +} + +static inline int serialDeviceWrite(SerialDeviceHandle deviceHandle, char* buffer, int bytesToWrite) { + return write(deviceHandle, buffer, bytesToWrite); +} + +static inline int serialDeviceRead(SerialDeviceHandle deviceHandle, char* buffer, int bytesToRead) { + return read(deviceHandle, buffer, bytesToRead); +} +#endif + +#endif /* _SERIAL_PORT_H_ */ +