version 0.2

* added support for Win32/64 builds
* fixed Mac OSX serial connection parameters
This commit is contained in:
ole00 2019-03-24 00:08:17 +00:00
parent 2c6ada613d
commit d5744a7d1a
4 changed files with 201 additions and 41 deletions

View File

@ -30,6 +30,9 @@ Requires:
Changelog: Changelog:
* 2019.02.02 - initial version 0.1 * 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. This is the PC part that communicates with Arduino UNO by serial line.
To compile: gcc -g3 -O0 afterburner afterburner.c To compile: gcc -g3 -O0 afterburner afterburner.c
@ -40,14 +43,12 @@ To compile: gcc -g3 -O0 afterburner afterburner.c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <termios.h> #include "serial_port.h"
#define VERSION "v.0.2"
#define VERSION "v.0.1"
#define DEFAULT_DEVICE_NAME "/dev/ttyUSB0"
#define MAX_LINE 200 #define MAX_LINE 200
@ -98,7 +99,7 @@ char verbose = 0;
char* filename = 0; char* filename = 0;
char* deviceName = 0; char* deviceName = 0;
int serialF = -1; SerialDeviceHandle serialF = INVALID_HANDLE;
Galtype gal; Galtype gal;
int security = 0; int security = 0;
unsigned short checksum; unsigned short checksum;
@ -131,7 +132,7 @@ static void printHelp() {
printf(" -v : verbose mode\n"); printf(" -v : verbose mode\n");
printf(" -t <gal_type> : the GAL type. use GAL16V8 GAL20V8 GAL22V10 ATF16V8B ATF22V10B ATF22V10C\n"); printf(" -t <gal_type> : the GAL type. use GAL16V8 GAL20V8 GAL22V10 ATF16V8B ATF22V10B ATF22V10C\n");
printf(" -f <file> : JEDEC fuse map file\n"); printf(" -f <file> : JEDEC fuse map file\n");
printf(" -d <serial_device> : name of the serial device. Default is: %s\n", DEFAULT_DEVICE_NAME); printf(" -d <serial_device> : name of the serial device. Default is: %s\n", DEFAULT_SERIAL_DEVICE_NAME);
printf(" serial params are: 38400, 8N1\n"); printf(" serial params are: 38400, 8N1\n");
printf("examples:\n"); printf("examples:\n");
printf(" afterburner i : reads and prints the device info\n"); printf(" afterburner i : reads and prints the device info\n");
@ -462,48 +463,29 @@ static char readJedec(void) {
static int openSerial(void) { static int openSerial(void) {
char buf[512]; char buf[512];
char devName[16]; char devName[256] = {0};
int total; int total;
int labelPos; int labelPos;
//open device name //open device name
snprintf(devName, 15, "%s", (deviceName == 0) ? DEFAULT_DEVICE_NAME : deviceName); snprintf(devName, sizeof(devName), "%s", (deviceName == 0) ? DEFAULT_SERIAL_DEVICE_NAME : deviceName);
devName[15] = 0; serialDeviceCheckName(devName, sizeof(devName));
if (verbose) { if (verbose) {
printf("opening serial: %s\n", devName); printf("opening serial: %s\n", devName);
} }
serialF = open(devName, O_RDWR | O_NOCTTY | O_NONBLOCK); serialF = serialDeviceOpen(devName);
if (serialF < 1) { if (serialF == INVALID_HANDLE) {
printf("Error: failed to open serial device: %s\n", devName); printf("Error: failed to open serial device: %s\n", devName);
return -2; 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 // prod the programmer to output it's identification
sprintf(buf, "*\r"); sprintf(buf, "*\r");
write(serialF, buf, 2); serialDeviceWrite(serialF, buf, 2);
//read programmer's message //read programmer's message
total = waitForSerialPrompt(buf, 512, 3000); total = waitForSerialPrompt(buf, 512, 3000);
@ -519,17 +501,17 @@ static int openSerial(void) {
if (verbose) { if (verbose) {
printf("Output from programmer not recognised: %s\n", buf); printf("Output from programmer not recognised: %s\n", buf);
} }
close(serialF); serialDeviceClose(serialF);
serialF = 0; serialF = INVALID_HANDLE;
return -4; return -4;
} }
static void closeSerial(void) { static void closeSerial(void) {
if (0 == serialF) { if (INVALID_HANDLE == serialF) {
return; return;
} }
close(serialF); serialDeviceClose(serialF);
serialF = 0; serialF = INVALID_HANDLE;
} }
@ -583,7 +565,7 @@ static int waitForSerialPrompt(char* buf, int bufSize, int maxDelay) {
memset(buf, 0, bufSize); memset(buf, 0, bufSize);
while (maxDelay > 0) { while (maxDelay > 0) {
readSize = read(serialF, buf, bufSize); readSize = serialDeviceRead(serialF, buf, bufSize);
if (readSize > 0) { if (readSize > 0) {
bufPos += readSize; bufPos += readSize;
if (checkPromptExists(bufStart, bufTotal) >= 0) { if (checkPromptExists(bufStart, bufTotal) >= 0) {
@ -606,7 +588,7 @@ static int sendLine(char* buf, int bufSize, int maxDelay) {
int writeSize; int writeSize;
char* obuf = buf; char* obuf = buf;
if (serialF == 0) { if (serialF == INVALID_HANDLE) {
return -1; return -1;
} }
@ -618,9 +600,9 @@ static int sendLine(char* buf, int bufSize, int maxDelay) {
// write the query into the modem's file // write the query into the modem's file
// file is opened non blocking so we have to ensure all contents is written // file is opened non blocking so we have to ensure all contents is written
while (total > 0) { while (total > 0) {
writeSize = write(serialF, buf, total); writeSize = serialDeviceWrite(serialF, buf, total);
if (writeSize < 0) { if (writeSize < 0) {
printf("ERROR: written: %i", writeSize); printf("ERROR: written: %i (%s)\n", writeSize, strerror(errno));
return -4; return -4;
} }
buf += writeSize; buf += writeSize;

4
compile_win32.sh Executable file
View File

@ -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_

4
compile_win64.sh Executable file
View File

@ -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_

170
serial_port.h Normal file
View File

@ -0,0 +1,170 @@
#ifndef _SERIAL_PORT_H_
#define _SERIAL_PORT_H_
#ifdef _USE_WIN_API_
#include <windows.h>
#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 <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#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_ */