Add files for building for Windows and an updated Makefile that will build for Mac OS, Linux, and Windows.
This commit is contained in:
parent
58ad1d3f9e
commit
5412955a7b
88
Makefile
88
Makefile
@ -1,8 +1,86 @@
|
|||||||
p1load: p1load.c ploader.c osint_linux.c
|
MKDIR=mkdir -p
|
||||||
cc -Wall -DMACOSX -o $@ p1load.c ploader.c osint_linux.c
|
RM=rm
|
||||||
|
CC=cc
|
||||||
|
ECHO=echo
|
||||||
|
|
||||||
run: p1load
|
OS?=macosx
|
||||||
./p1load blink.binary -r -t
|
|
||||||
|
|
||||||
|
ifeq ($(OS),linux)
|
||||||
|
CFLAGS+=-DLINUX
|
||||||
|
EXT=
|
||||||
|
OSINT=osint_linux
|
||||||
|
LIBS=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),msys)
|
||||||
|
CFLAGS += -DMINGW
|
||||||
|
EXT=.exe
|
||||||
|
OSINT=osint_mingw enumcom
|
||||||
|
LIBS=-lsetupapi
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),macosx)
|
||||||
|
CFLAGS+=-DMACOSX
|
||||||
|
EXT=
|
||||||
|
OSINT=osint_linux
|
||||||
|
LIBS=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),)
|
||||||
|
$(error OS not set)
|
||||||
|
endif
|
||||||
|
|
||||||
|
SRCDIR=.
|
||||||
|
OBJDIR=obj/$(OS)
|
||||||
|
BINDIR=bin/$(OS)
|
||||||
|
|
||||||
|
TARGET=$(BINDIR)/p1load$(EXT)
|
||||||
|
|
||||||
|
HDRS=\
|
||||||
|
ploader.h
|
||||||
|
|
||||||
|
OBJS=\
|
||||||
|
$(OBJDIR)/p1load.o \
|
||||||
|
$(OBJDIR)/ploader.o \
|
||||||
|
$(foreach x, $(OSINT), $(OBJDIR)/$(x).o)
|
||||||
|
|
||||||
|
CFLAGS+=-Wall
|
||||||
|
LDFLAGS=$(CFLAGS)
|
||||||
|
|
||||||
|
.PHONY: default
|
||||||
|
default: $(TARGET)
|
||||||
|
|
||||||
|
DIRS=$(OBJDIR) $(BINDIR)
|
||||||
|
|
||||||
|
$(TARGET): $(BINDIR) $(OBJDIR) $(OBJS)
|
||||||
|
@$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||||
|
@$(ECHO) link $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HDRS) $(OBJDIR)
|
||||||
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
@$(ECHO) $(CC) $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(OBJDIR)/%.c $(HDRS) $(OBJDIR)
|
||||||
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
@$(ECHO) $(CC) $@
|
||||||
|
|
||||||
|
.PHONY: bin2c
|
||||||
|
bin2c: $(BINDIR)/bin2c$(EXT)
|
||||||
|
|
||||||
|
$(BINDIR)/bin2c$(EXT): $(SRCDIR)/tools/bin2c.c $(BINDIR)
|
||||||
|
@$(CC) $(CFLAGS) $(LDFLAGS) $(SRCDIR)/tools/bin2c.c -o $@
|
||||||
|
@$(ECHO) cc $@
|
||||||
|
|
||||||
|
$(DIRS):
|
||||||
|
$(MKDIR) $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf p1load
|
@$(RM) -f -r $(OBJDIR)
|
||||||
|
@$(RM) -f -r $(PROPOBJDIR)
|
||||||
|
@$(RM) -f -r $(BINDIR)
|
||||||
|
|
||||||
|
.PHONY:
|
||||||
|
clean-all: clean
|
||||||
|
@$(RM) -f -r obj
|
||||||
|
@$(RM) -f -r bin
|
||||||
|
141
enumcom.c
Executable file
141
enumcom.c
Executable file
@ -0,0 +1,141 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
* Derived from code by Zach Gorman with the following license:
|
||||||
|
*
|
||||||
|
* Serial port enumeration routines
|
||||||
|
*
|
||||||
|
* The EnumSerialPort function will populate an array of SSerInfo structs,
|
||||||
|
* each of which contains information about one serial port present in
|
||||||
|
* the system. Note that this code must be linked with setupapi.lib,
|
||||||
|
* which is included with the Win32 SDK.
|
||||||
|
*
|
||||||
|
* by Zach Gorman <gormanjz@hotmail.com>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002 Archetype Auction Software, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following condition is
|
||||||
|
* met: Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this condition and the following disclaimer.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL ARCHETYPE AUCTION SOFTWARE OR ITS
|
||||||
|
* AFFILIATES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <initguid.h>
|
||||||
|
#include <objbase.h>
|
||||||
|
#include <setupapi.h>
|
||||||
|
|
||||||
|
#ifndef GUID_DEVINTERFACE_COMPORT
|
||||||
|
DEFINE_GUID(GUID_DEVINTERFACE_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAIN
|
||||||
|
int CheckPort(const char* port, void* data)
|
||||||
|
{
|
||||||
|
printf("Found %s\n", port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("serial_file returned %d\n", serial_find(NULL, CheckPort, NULL));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int serial_find(const char* prefix, int (*check)(const char* port, void* data), void* data)
|
||||||
|
{
|
||||||
|
GUID *guidDev = (GUID *) &GUID_DEVINTERFACE_COMPORT;
|
||||||
|
HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
|
||||||
|
SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL;
|
||||||
|
SP_DEVICE_INTERFACE_DATA ifcData;
|
||||||
|
DWORD dwDetDataSize;
|
||||||
|
int rc = -1;
|
||||||
|
BOOL bOk;
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
hDevInfo = SetupDiGetClassDevs( guidDev,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
|
||||||
|
);
|
||||||
|
|
||||||
|
if(hDevInfo == INVALID_HANDLE_VALUE) {
|
||||||
|
printf("error: SetupDiGetClassDevs failed. (err=%lx)\n", GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enumerate the serial ports
|
||||||
|
dwDetDataSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + 256;
|
||||||
|
pDetData = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(dwDetDataSize);
|
||||||
|
|
||||||
|
ifcData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||||
|
pDetData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||||
|
|
||||||
|
for (i = 0, bOk = TRUE; bOk; ++i) {
|
||||||
|
|
||||||
|
// get the next device
|
||||||
|
bOk = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guidDev, i, &ifcData);
|
||||||
|
if (bOk) {
|
||||||
|
|
||||||
|
// get the device details
|
||||||
|
SP_DEVINFO_DATA devdata = {sizeof(SP_DEVINFO_DATA)};
|
||||||
|
bOk = SetupDiGetDeviceInterfaceDetail(hDevInfo, &ifcData, pDetData, dwDetDataSize, NULL, &devdata);
|
||||||
|
if (bOk) {
|
||||||
|
TCHAR fname[256], desc[256];
|
||||||
|
|
||||||
|
// get some additional info
|
||||||
|
BOOL bSuccess = SetupDiGetDeviceRegistryProperty(hDevInfo, &devdata, SPDRP_FRIENDLYNAME, NULL, (PBYTE)fname, sizeof(fname), NULL)
|
||||||
|
&& SetupDiGetDeviceRegistryProperty(hDevInfo, &devdata, SPDRP_DEVICEDESC, NULL, (PBYTE)desc, sizeof(desc), NULL);
|
||||||
|
if (bSuccess) {
|
||||||
|
char *comx, *p;
|
||||||
|
//printf("Device path: %s\n", pDetData->DevicePath);
|
||||||
|
//printf("Friendly name: %s\n", fname);
|
||||||
|
//printf("Description: %s\n", desc);
|
||||||
|
if ((comx = strchr(fname, '(')) != NULL)
|
||||||
|
++comx;
|
||||||
|
else
|
||||||
|
comx = fname;
|
||||||
|
if ((p = strchr(comx, ')')) != NULL)
|
||||||
|
*p = '\0';
|
||||||
|
if ((*check)(comx, data) == 0) {
|
||||||
|
rc = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("error: SetupDiGetDeviceInterfaceDetail failed. (err=%lx)\n", GetLastError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DWORD err = GetLastError();
|
||||||
|
if (err != ERROR_NO_MORE_ITEMS) {
|
||||||
|
printf("error: SetupDiEnumDeviceInterfaces failed. (err=%lx)\n", err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (pDetData != NULL)
|
||||||
|
free(pDetData);
|
||||||
|
if (hDevInfo != INVALID_HANDLE_VALUE)
|
||||||
|
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
322
osint_mingw.c
Executable file
322
osint_mingw.c
Executable file
@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
* osint_mingw.c - serial i/o routines for win32api via mingw
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 by Steve Denson.
|
||||||
|
*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <conio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "osint.h"
|
||||||
|
|
||||||
|
static HANDLE hSerial = INVALID_HANDLE_VALUE;
|
||||||
|
static COMMTIMEOUTS original_timeouts;
|
||||||
|
static COMMTIMEOUTS timeouts;
|
||||||
|
|
||||||
|
static void ShowLastError(void);
|
||||||
|
|
||||||
|
/* normally we use DTR for reset but setting this variable to non-zero will use RTS instead */
|
||||||
|
static int use_rts_for_reset = 0;
|
||||||
|
|
||||||
|
void serial_use_rts_for_reset(int use_rts)
|
||||||
|
{
|
||||||
|
use_rts_for_reset = use_rts;
|
||||||
|
}
|
||||||
|
|
||||||
|
int serial_init(const char *port, unsigned long baud)
|
||||||
|
{
|
||||||
|
char fullPort[20];
|
||||||
|
|
||||||
|
sprintf(fullPort, "\\\\.\\%s", port);
|
||||||
|
|
||||||
|
hSerial = CreateFile(
|
||||||
|
fullPort,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (hSerial == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Set the baud rate. Always succeeds with mingw. */
|
||||||
|
if (!serial_baud(baud)) {
|
||||||
|
serial_done();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GetCommTimeouts(hSerial, &original_timeouts);
|
||||||
|
timeouts = original_timeouts;
|
||||||
|
timeouts.ReadIntervalTimeout = MAXDWORD;
|
||||||
|
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
|
||||||
|
timeouts.WriteTotalTimeoutConstant = 1;
|
||||||
|
timeouts.WriteTotalTimeoutMultiplier = 1;
|
||||||
|
|
||||||
|
/* setup device buffers */
|
||||||
|
SetupComm(hSerial, 10000, 10000);
|
||||||
|
|
||||||
|
/* purge any information in the buffer */
|
||||||
|
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_done(void)
|
||||||
|
{
|
||||||
|
if (hSerial != INVALID_HANDLE_VALUE) {
|
||||||
|
FlushFileBuffers(hSerial);
|
||||||
|
CloseHandle(hSerial);
|
||||||
|
hSerial = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* change the baud rate of the serial port
|
||||||
|
* @param baud - baud rate
|
||||||
|
* @returns 1 for success and 0 for failure
|
||||||
|
*/
|
||||||
|
int serial_baud(unsigned long baud)
|
||||||
|
{
|
||||||
|
DCB state;
|
||||||
|
GetCommState(hSerial, &state);
|
||||||
|
switch (baud) {
|
||||||
|
case 9600:
|
||||||
|
state.BaudRate = CBR_9600;
|
||||||
|
break;
|
||||||
|
case 19200:
|
||||||
|
state.BaudRate = CBR_19200;
|
||||||
|
break;
|
||||||
|
case 38400:
|
||||||
|
state.BaudRate = CBR_38400;
|
||||||
|
break;
|
||||||
|
case 57600:
|
||||||
|
state.BaudRate = CBR_57600;
|
||||||
|
break;
|
||||||
|
case 115200:
|
||||||
|
state.BaudRate = CBR_115200;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unsupported baudrate. Use ");
|
||||||
|
printf("115200, 57600, 38400, 19200, or 9600\n");
|
||||||
|
printf("Setting default 115200\n");
|
||||||
|
state.BaudRate = CBR_115200;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.ByteSize = 8;
|
||||||
|
state.Parity = NOPARITY;
|
||||||
|
state.StopBits = ONESTOPBIT;
|
||||||
|
state.fOutxDsrFlow = FALSE;
|
||||||
|
state.fDtrControl = DTR_CONTROL_DISABLE;
|
||||||
|
state.fOutxCtsFlow = FALSE;
|
||||||
|
state.fRtsControl = RTS_CONTROL_DISABLE;
|
||||||
|
state.fInX = FALSE;
|
||||||
|
state.fOutX = FALSE;
|
||||||
|
state.fBinary = TRUE;
|
||||||
|
state.fParity = FALSE;
|
||||||
|
state.fDsrSensitivity = FALSE;
|
||||||
|
state.fTXContinueOnXoff = TRUE;
|
||||||
|
state.fNull = FALSE;
|
||||||
|
state.fAbortOnError = FALSE;
|
||||||
|
SetCommState(hSerial, &state);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transmit a buffer
|
||||||
|
* @param buff - char pointer to buffer
|
||||||
|
* @param n - number of bytes in buffer to send
|
||||||
|
* @returns zero on failure
|
||||||
|
*/
|
||||||
|
int tx(uint8_t* buff, int n)
|
||||||
|
{
|
||||||
|
DWORD dwBytes = 0;
|
||||||
|
if(!WriteFile(hSerial, buff, n, &dwBytes, NULL)){
|
||||||
|
printf("Error writing port\n");
|
||||||
|
ShowLastError();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return dwBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* receive a buffer
|
||||||
|
* @param buff - char pointer to buffer
|
||||||
|
* @param n - number of bytes in buffer to read
|
||||||
|
* @returns number of bytes read
|
||||||
|
*/
|
||||||
|
int rx(uint8_t* buff, int n)
|
||||||
|
{
|
||||||
|
DWORD dwBytes = 0;
|
||||||
|
SetCommTimeouts(hSerial, &original_timeouts);
|
||||||
|
if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){
|
||||||
|
printf("Error reading port\n");
|
||||||
|
ShowLastError();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return dwBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* receive a buffer with a timeout
|
||||||
|
* @param buff - char pointer to buffer
|
||||||
|
* @param n - number of bytes in buffer to read
|
||||||
|
* @param timeout - timeout in milliseconds
|
||||||
|
* @returns number of bytes read or SERIAL_TIMEOUT
|
||||||
|
*/
|
||||||
|
int rx_timeout(uint8_t* buff, int n, int timeout)
|
||||||
|
{
|
||||||
|
DWORD dwBytes = 0;
|
||||||
|
timeouts.ReadTotalTimeoutConstant = timeout;
|
||||||
|
SetCommTimeouts(hSerial, &timeouts);
|
||||||
|
if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){
|
||||||
|
printf("Error reading port\n");
|
||||||
|
ShowLastError();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return dwBytes > 0 ? dwBytes : SERIAL_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hwreset ... resets Propeller hardware using DTR
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
void hwreset(void)
|
||||||
|
{
|
||||||
|
// reset then purge port
|
||||||
|
EscapeCommFunction(hSerial, use_rts_for_reset ? SETRTS : SETDTR);
|
||||||
|
Sleep(25);
|
||||||
|
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
|
||||||
|
EscapeCommFunction(hSerial, use_rts_for_reset ? CLRRTS : CLRDTR);
|
||||||
|
Sleep(90);
|
||||||
|
// Purge here after reset helps to get rid of buffered data.
|
||||||
|
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long getms()
|
||||||
|
{
|
||||||
|
LARGE_INTEGER ticksPerSecond;
|
||||||
|
LARGE_INTEGER tick; // A point in time
|
||||||
|
LARGE_INTEGER time; // For converting tick into real time
|
||||||
|
// get the high resolution counter's accuracy
|
||||||
|
QueryPerformanceFrequency(&ticksPerSecond);
|
||||||
|
if(ticksPerSecond.QuadPart < 1000) {
|
||||||
|
printf("Your system does not meet timer requirement. Try another computer. Exiting program.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
// what time is it?
|
||||||
|
QueryPerformanceCounter(&tick);
|
||||||
|
time.QuadPart = (tick.QuadPart*1000/ticksPerSecond.QuadPart);
|
||||||
|
return (unsigned long)(time.QuadPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sleep for ms milliseconds
|
||||||
|
* @param ms - time to wait in milliseconds
|
||||||
|
*/
|
||||||
|
void msleep(int ms)
|
||||||
|
{
|
||||||
|
unsigned long t = getms();
|
||||||
|
while((t+ms+10) > getms())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowLastError(void)
|
||||||
|
{
|
||||||
|
LPVOID lpMsgBuf;
|
||||||
|
FormatMessage(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
GetLastError(),
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
(LPTSTR)&lpMsgBuf,
|
||||||
|
0, NULL);
|
||||||
|
printf(" %s\n", (char *)lpMsgBuf);
|
||||||
|
LocalFree(lpMsgBuf);
|
||||||
|
exit(1); // exit on error
|
||||||
|
}
|
||||||
|
|
||||||
|
/* escape from terminal mode */
|
||||||
|
#define ESC 0x1b
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if "check_for_exit" is true, then
|
||||||
|
* a sequence EXIT_CHAR 00 nn indicates that we should exit
|
||||||
|
*/
|
||||||
|
#define EXIT_CHAR 0xff
|
||||||
|
|
||||||
|
void terminal_mode(int check_for_exit, int pst_mode)
|
||||||
|
{
|
||||||
|
int sawexit_char = 0;
|
||||||
|
int sawexit_valid = 0;
|
||||||
|
int exitcode = 0;
|
||||||
|
int continue_terminal = 1;
|
||||||
|
|
||||||
|
while (continue_terminal) {
|
||||||
|
uint8_t buf[1];
|
||||||
|
if (rx_timeout(buf, 1, 0) != SERIAL_TIMEOUT) {
|
||||||
|
if (sawexit_valid) {
|
||||||
|
exitcode = buf[0];
|
||||||
|
continue_terminal = 0;
|
||||||
|
}
|
||||||
|
else if (sawexit_char) {
|
||||||
|
if (buf[0] == 0) {
|
||||||
|
sawexit_valid = 1;
|
||||||
|
} else {
|
||||||
|
putchar(EXIT_CHAR);
|
||||||
|
putchar(buf[0]);
|
||||||
|
fflush(stdout);
|
||||||
|
//sawexit_char = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (check_for_exit && buf[0] == EXIT_CHAR) {
|
||||||
|
sawexit_char = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
putchar(buf[0]);
|
||||||
|
if (pst_mode && buf[0] == '\r')
|
||||||
|
putchar('\n');
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (kbhit()) {
|
||||||
|
if ((buf[0] = getch()) == ESC)
|
||||||
|
break;
|
||||||
|
tx(buf, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_for_exit && sawexit_valid) {
|
||||||
|
exit(exitcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user