initial commit
This commit is contained in:
commit
c1e41270e0
|
@ -0,0 +1,46 @@
|
|||
* Version 1.2.0 (20100306)
|
||||
- adopted to new build system (taken from flyer)
|
||||
|
||||
* Version 1.1.5 (20100306)
|
||||
- updated usart lib and sync timer
|
||||
|
||||
* Version 1.1.4 (20091212)
|
||||
- secured firmware command
|
||||
- rewritten modfify command handling to support new option
|
||||
- due to flaw in TurboEDIT's byte count in write W command
|
||||
added flag that decides how to treat bytecount in W command
|
||||
b_bcnt_mode = false => 0x00 means 256 bytes, 0xFF means 255 bytes
|
||||
b_bcnt_mode = true => 0x00 means 1 byte, 0xFF means 255 bytes
|
||||
NOTE: use b_cnt_mode = true only for TurboEDIT!
|
||||
- set default transmission parameters to:
|
||||
baudrate 920000, 2 stop bits, even parity
|
||||
(defaults for CROME 1.5.3 and above) - most frequent usage
|
||||
NOTE: due to flaw in CROME 1.5.3 and 1.5.5beta (older versions
|
||||
are not affected) serial port opening methods which discards
|
||||
any user settings in window and uses 9600 or 920000 baudrate
|
||||
|
||||
* Version 1.1.3 (20091207)
|
||||
- fixed usart_const computation issue in initUsart
|
||||
|
||||
* Version 1.1.2 (20091206)
|
||||
- fixed error flags handling in usart module
|
||||
|
||||
* Version 1.1.1 (20091206)
|
||||
- added response when parameters modification failed
|
||||
|
||||
* Version 1.1.0 (20091124)
|
||||
- due to compatibility issues default USART frame again is:
|
||||
baudrate 115200, 2 stop bits, no parity
|
||||
- general code cleanup
|
||||
- reduced clock cycles in memory handling
|
||||
- added new command: M - modify usart settings (using this
|
||||
allows to change usart parameters on the fly, what is
|
||||
needed for proper work with software tools from different
|
||||
suppliers
|
||||
- fixed acknowledge in for write block X (bytes order)
|
||||
|
||||
* Version 1.0.1 (20091118)
|
||||
- changed baudrate to 920000, because of bug in CROME newer than 1.5
|
||||
|
||||
* Version 1.0.0 (20091116)
|
||||
- initial release
|
|
@ -0,0 +1,53 @@
|
|||
SRCS=$(wildcard src/*.c)
|
||||
OBJS=$(subst .c,.o,$(subst src,obj,$(SRCS)))
|
||||
|
||||
CC=tools/avr-gcc
|
||||
OBJCOPY=avr-objcopy
|
||||
SIZE=avr-size
|
||||
MCU=atmega32
|
||||
|
||||
TARGET=$(shell basename `pwd`)
|
||||
VERSION=$(shell echo "$(TARGET)" | cut -d "-" -f 2-) build:$(shell date +%Y%m%d)
|
||||
|
||||
CFLAGS_DEF=-DFVERSION="\"$(VERSION)\""
|
||||
CFLAGS_MCU=-mmcu=$(MCU) -fomit-frame-pointer
|
||||
CFLAGS_OPT=-O2 -g0 -pipe -fshort-enums -fpack-struct -s
|
||||
CFLAGS_STD=-std=c99 -funsigned-char
|
||||
CFLAGS_WARN=-Wall -Wextra \
|
||||
-Wbad-function-cast -Wunused-parameter -Wshadow -Wpointer-arith -Wmissing-declarations \
|
||||
-Wmissing-noreturn -Wunreachable-code -Wdeclaration-after-statement -Wundef -Wmissing-braces
|
||||
|
||||
CFLAGS=$(CFLAGS_MCU) $(CFLAGS_OPT) $(CFLAGS_STD) $(CFLAGS_DEF)
|
||||
LDFLAGS=-Wl,-O1 -lm
|
||||
|
||||
all : $(TARGET).hex info
|
||||
|
||||
clean :
|
||||
rm -fr obj/*.o $(TARGET) $(TARGET).hex *.tar.bz2
|
||||
|
||||
dist : clean
|
||||
@echo -e "\nCREATED: $(TARGET).tar.bz2"
|
||||
$(shell cd .. ; tar --exclude=$(TARGET).tar.bz2 -cjf $(TARGET)/$(TARGET).tar.bz2 $(TARGET))
|
||||
|
||||
info : $(TARGET).hex
|
||||
@echo "built binary sections size:"
|
||||
@$(SIZE) --target=ihex $(TARGET).hex
|
||||
|
||||
program : $(TARGET).hex
|
||||
avrdude -p $(MCU)
|
||||
|
||||
obj/%.o : src/%.c
|
||||
@echo -e "\033[1;34m[CC]: \033[0m$(CC) $< -o $@ -c $(CFLAGS)"
|
||||
@$(CC) $(CFLAGS) $(CFLAGS_WARN) -c $< -o $@
|
||||
|
||||
$(TARGET) : $(OBJS)
|
||||
@echo -e "\033[1;32m[LD]: \033[0m$(CC) $^ -o $@ $(CFLAGS) $(LDFLAGS)"
|
||||
@$(CC) $(CFLAGS) $(CFLAGS_WARN) $(LDFLAGS) $^ -o $@
|
||||
|
||||
$(TARGET).hex : $(TARGET)
|
||||
@echo -n -e "\033[1;33m[HEX]: \033[0m"
|
||||
$(OBJCOPY) -O ihex -R .eeprom -R .fuse -R .lock $(TARGET) $@
|
||||
|
||||
@echo -e "\nBUILD COMPLETE!\n"
|
||||
|
||||
.PHONY : all clean dist info program
|
|
@ -0,0 +1,371 @@
|
|||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "comm.h"
|
||||
#include "memory.h"
|
||||
#include "usart.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* GLOBAL: tells how to treat byte_count in write W command */
|
||||
BOOL b_bcnt_mode = false;
|
||||
|
||||
/* GLOBAL: indicates device status */
|
||||
BOOL b_status_ready = false;
|
||||
|
||||
/* indicates whether last read byte from usart is ok */
|
||||
static BOOL b_read_ok = false;
|
||||
|
||||
/* holds latest read byte */
|
||||
static BYTE read_byte;
|
||||
|
||||
/* contains information about bytes to read/write in frame */
|
||||
static UINT16 byte_count;
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BYTE checksum(BYTE* buffer_ptr, const UINT16 length)
|
||||
{
|
||||
static UINT8 chksum;
|
||||
static UINT16 buffer_idx;
|
||||
|
||||
chksum = 0;
|
||||
|
||||
/* sum all bytes with no carry */
|
||||
for (buffer_idx = 0; buffer_idx < length; ++buffer_idx)
|
||||
chksum += buffer_ptr[buffer_idx];
|
||||
|
||||
return (chksum);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandBytecountMode()
|
||||
{
|
||||
/* 1: mode, 2: checksum */
|
||||
data_buffer[0] = read_byte;
|
||||
if (!usartRead(data_buffer + 1, 2, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
/* if checksum is ok, set byte_count computation method flag */
|
||||
if (checksum(data_buffer, 2) == data_buffer[2])
|
||||
{
|
||||
b_bcnt_mode = (data_buffer[1])?(true):(false);
|
||||
/* acknowledge action */
|
||||
usartSendByte('O');
|
||||
}
|
||||
/* otherwise inform that parameter modification failed */
|
||||
else
|
||||
usartSendByte('F');
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandFirmware()
|
||||
{
|
||||
if (!usartRead(data_buffer, 1, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
if (read_byte == data_buffer[0])
|
||||
{
|
||||
/* respond with firmware version number ... */
|
||||
usartSendString_P((BYTE*)PSTR("honda-rtp, ver. "));
|
||||
usartSendString_P((BYTE*)PSTR(FIRMWARE_VERSION));
|
||||
|
||||
/* ... with compiler and library version number */
|
||||
usartSendString_P((BYTE*)PSTR(", avr-libc: "));
|
||||
usartSendString_P((BYTE*)PSTR(__AVR_LIBC_VERSION_STRING__));
|
||||
usartSendString_P((BYTE*)PSTR(", avr-gcc: "));
|
||||
usartSendString_P((BYTE*)PSTR(__VERSION__));
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandModify()
|
||||
{
|
||||
UINT16 baudrate;
|
||||
UINT16 delay;
|
||||
|
||||
/* 1: baudrate hi byte, 2: baudrate lo byte, 3: double speed, 4: two stop bits, 5: parity, 6: checksum */
|
||||
data_buffer[0] = read_byte;
|
||||
if (!usartRead(data_buffer + 1, 6, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
/* if checksum is ok, reinitialize usart */
|
||||
if (checksum(data_buffer, 6) == data_buffer[6])
|
||||
{
|
||||
/* acknowledge action and wait for transmission completion */
|
||||
usartSendByte('O');
|
||||
for (delay = 0; delay < 0xFFFF; ++delay)
|
||||
NOP_DELAY;
|
||||
|
||||
baudrate = (UINT16)(data_buffer[1] << 8) + (UINT16)(data_buffer[2]);
|
||||
initUsart(baudrate, data_buffer[3], data_buffer[4], data_buffer[5]);
|
||||
}
|
||||
/* otherwise inform that parameter modification failed */
|
||||
else
|
||||
usartSendByte('F');
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandReadBlock()
|
||||
{
|
||||
/* indicate whether device is busy */
|
||||
b_status_ready = false;
|
||||
|
||||
/* 1: bytes to read, 2: addr hi byte, 3: addr lo byte, 4: checksum */
|
||||
data_buffer[0] = read_byte;
|
||||
if (!usartRead(data_buffer + 1, 4, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
/* if checksum is ok, read data from memory */
|
||||
if (checksum(data_buffer, 4) == data_buffer[4])
|
||||
{
|
||||
/* 0 for 256 bytes of data */
|
||||
byte_count = (data_buffer[1])?(data_buffer[1]):(256);
|
||||
|
||||
memoryReadBlock((UINT16)(data_buffer[2] << 8) + (UINT16)(data_buffer[3]), byte_count, data_buffer);
|
||||
data_buffer[byte_count] = checksum(data_buffer, byte_count);
|
||||
|
||||
/* send data read from memory with checksum */
|
||||
usartSend(data_buffer, byte_count + 1);
|
||||
}
|
||||
|
||||
/* after all enable ECU to read from device */
|
||||
setMemoryAccessEcuRead();
|
||||
|
||||
/* indicate whether device is ready */
|
||||
b_status_ready = true;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandReadByte()
|
||||
{
|
||||
/* indicate whether device is busy */
|
||||
b_status_ready = false;
|
||||
|
||||
if (!usartRead(data_buffer, 2, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
/* 1: addr hi byte, 2: addr lo byte */
|
||||
data_buffer[2] = *(memoryRead((UINT16)(data_buffer[0] << 8) + (UINT16)(data_buffer[1])));
|
||||
|
||||
usartSendByte(data_buffer[2]);
|
||||
|
||||
/* after all enable ECU to read from device */
|
||||
setMemoryAccessEcuRead();
|
||||
|
||||
/* indicate whether device is ready */
|
||||
b_status_ready = true;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandStatus()
|
||||
{
|
||||
/* respond with 'O' when device is ready or with 'B' when busy */
|
||||
data_buffer[0] = (b_status_ready)?('O'):('B');
|
||||
data_buffer[1] = checksum(data_buffer, 1);
|
||||
usartSend(data_buffer, 2);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandUnknown()
|
||||
{
|
||||
data_buffer[0] = UNKNOWN;
|
||||
data_buffer[1] = checksum(data_buffer, 1);
|
||||
usartSend(data_buffer, 2);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandVersion()
|
||||
{
|
||||
if (!usartRead(data_buffer, 1, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
if (read_byte == data_buffer[0])
|
||||
{
|
||||
data_buffer[1] = ROMULATOR_PROTOCOL_MAJOR;
|
||||
data_buffer[2] = ROMULATOR_PROTOCOL_MINOR;
|
||||
data_buffer[3] = ROMULATOR_PROTOCOL_ID;
|
||||
|
||||
usartSend(data_buffer + 1, 3);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandVersionResp()
|
||||
{
|
||||
/* WORKAROUND: discard data received as response to version command */
|
||||
usartRead(data_buffer, 4, 1);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandWriteW()
|
||||
{
|
||||
/* indicate whether device is busy */
|
||||
b_status_ready = false;
|
||||
|
||||
/* 0: command, 1: number of bytes to write, 2: addr hi byte, 3: addr lo byte */
|
||||
data_buffer[0] = read_byte;
|
||||
if (!usartRead(data_buffer + 1, 3, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
/* WORKAROUND: due to flaw in TurboEDIT's byte count computatnion method */
|
||||
if (!b_bcnt_mode)
|
||||
byte_count = (data_buffer[1])?(data_buffer[1]):(256);
|
||||
else
|
||||
byte_count = data_buffer[1] + 1;
|
||||
|
||||
/* timeout waiting for byte after 50 ms */
|
||||
if (!usartRead((data_buffer + 4), byte_count + 1, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
if (checksum(data_buffer, byte_count + 4) != data_buffer[byte_count + 4])
|
||||
return;
|
||||
|
||||
/* try to write block of bytes few times */
|
||||
for (UINT8 i = 0; i < ROMULATOR_PROTOCOL_WRITE_RETRIES; ++i)
|
||||
{
|
||||
if (memoryWriteBlock((UINT16)(data_buffer[2] << 8) + (UINT16)(data_buffer[3]), byte_count, data_buffer + 4))
|
||||
{
|
||||
/* acknowledge that block was written properly */
|
||||
usartSendByte('O');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* after all enable ECU to read from device */
|
||||
setMemoryAccessEcuRead();
|
||||
|
||||
/* indicate whether device is ready */
|
||||
b_status_ready = true;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommandWriteX()
|
||||
{
|
||||
static UINT16 wr_checksum;
|
||||
|
||||
/* indicate whether device is busy */
|
||||
b_status_ready = false;
|
||||
|
||||
/* 0: command, 1: number of bytes to write, 2: addr hi byte, 3: addr lo byte */
|
||||
data_buffer[0] = read_byte;
|
||||
if (!usartRead(data_buffer + 1, 3, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
byte_count = (data_buffer[1])?(data_buffer[1]):(256);
|
||||
|
||||
/* timeout waiting for byte after 50 ms */
|
||||
if (!usartRead((data_buffer + 4), byte_count + 1, ROMULATOR_PROTOCOL_READ_TIMEOUT))
|
||||
return;
|
||||
|
||||
if (checksum(data_buffer, byte_count + 4) != data_buffer[byte_count + 4])
|
||||
return;
|
||||
|
||||
/* try to write block of bytes few times */
|
||||
for (UINT8 i = 0; i < ROMULATOR_PROTOCOL_WRITE_RETRIES; ++i)
|
||||
{
|
||||
if (memoryWriteBlock((UINT16)(data_buffer[2] << 8) + (UINT16)(data_buffer[3]), byte_count, data_buffer + 4))
|
||||
{
|
||||
/* acknowledge that block was written properly - two byte checksum */
|
||||
wr_checksum = 0;
|
||||
|
||||
for (UINT16 j = 0; j < byte_count; ++j)
|
||||
wr_checksum += data_buffer[4 + j];
|
||||
|
||||
data_buffer[0] = wr_checksum;
|
||||
data_buffer[1] = (wr_checksum >> 8);
|
||||
|
||||
usartSend(data_buffer, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* after all enable ECU to read from device */
|
||||
setMemoryAccessEcuRead();
|
||||
|
||||
/* indicate whether device is ready */
|
||||
b_status_ready = true;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void pcCommand()
|
||||
{
|
||||
read_byte = usartReadByte(&b_read_ok);
|
||||
|
||||
if (b_read_ok)
|
||||
{
|
||||
/* treat each first incoming byte as command */
|
||||
switch (read_byte)
|
||||
{
|
||||
case BYTECOUNT_MODE:
|
||||
pcCommandBytecountMode();
|
||||
|
||||
break;
|
||||
case FIRMWARE:
|
||||
pcCommandFirmware();
|
||||
break;
|
||||
|
||||
case MODIFY:
|
||||
pcCommandModify();
|
||||
break;
|
||||
|
||||
case READ_BLOCK:
|
||||
pcCommandReadBlock();
|
||||
break;
|
||||
|
||||
case READ_BYTE:
|
||||
pcCommandReadByte();
|
||||
break;
|
||||
|
||||
case STATUS:
|
||||
pcCommandStatus();
|
||||
break;
|
||||
|
||||
case VERSION:
|
||||
pcCommandVersion();
|
||||
break;
|
||||
|
||||
case VERSION_RESP:
|
||||
pcCommandVersionResp();
|
||||
break;
|
||||
|
||||
case WRITE_X:
|
||||
pcCommandWriteX();
|
||||
break;
|
||||
|
||||
case WRITE_W:
|
||||
pcCommandWriteW();
|
||||
break;
|
||||
|
||||
case WRITE_H:
|
||||
/* treat as normal write to memory, due to hardware limitations */
|
||||
pcCommandWriteW();
|
||||
break;
|
||||
|
||||
default:
|
||||
pcCommandUnknown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
|
@ -0,0 +1,155 @@
|
|||
#ifndef _COMM_H
|
||||
#define _COMM_H
|
||||
|
||||
/**************************************************************************
|
||||
* Written by Marcin O'BenY Benka <obeny@obeny.net>
|
||||
* Version 1.1.4 (20091212)
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* Communication with PC using Xtronics ROMulator protocol.
|
||||
**************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* GLOBAL: tells how to treat byte_count in W write command */
|
||||
extern BOOL b_bcnt_mode;
|
||||
|
||||
/* GLOBAL: indicates device status */
|
||||
extern BOOL b_status_ready;
|
||||
|
||||
/* supported PC commands */
|
||||
enum e_command
|
||||
{
|
||||
/* Xtronics ROMulator commands */
|
||||
READ_BLOCK = 'R',
|
||||
READ_BYTE = 'r',
|
||||
STATUS = 'S',
|
||||
UNKNOWN = '?',
|
||||
VERSION = 'V',
|
||||
WRITE_H = 'w',
|
||||
WRITE_W = 'W',
|
||||
WRITE_X = 'X',
|
||||
|
||||
/* extended commands for own usage */
|
||||
BYTECOUNT_MODE = 'B',
|
||||
FIRMWARE = 'F',
|
||||
MODIFY = 'M',
|
||||
VERSION_RESP = 'E', /* dirty workaround for ROMulator 'V' command */
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* counts checksum of given bytes */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : added all bytes with no carry
|
||||
ARGS : buffer_ptr - buffer pointer
|
||||
length - number of bytes to add
|
||||
* ----------------------------------------------------------------------- */
|
||||
BYTE checksum(BYTE* buffer_ptr, const UINT16 length);
|
||||
|
||||
/* process command from PC */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void pcCommand();
|
||||
|
||||
/* modifies current byte_count handling method */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void pcCommandBytecountMode();
|
||||
|
||||
/* return version of installed firmware */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void pcCommandFirmware();
|
||||
|
||||
/* modifies current usart settings */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void pcCommandModify();
|
||||
|
||||
/* upload to PC block of data */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void pcCommandReadBlock();
|
||||
|
||||
/* upload to PC single byte of data */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void pcCommandReadByte();
|
||||
|
||||
/* process command from PC */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
void pcCommandStatus();
|
||||
/* tells whether device is ready to work */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
void pcCommandUnknown();
|
||||
/* illegal command received */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
void pcCommandVersion();
|
||||
/* returns device version */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
void pcCommandVersionResp();
|
||||
/* discards data sent by program as acknowledge of received version */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
void pcCommandWriteW();
|
||||
/* download to uC block of data (used also for hidden-write) */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
void pcCommandWriteX();
|
||||
/* download to uC block of data */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#endif /* _COMM_H */
|
||||
/* END */
|
|
@ -0,0 +1,119 @@
|
|||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
/**************************************************************************
|
||||
* PROJECT: Honda RTP rev. 1.0
|
||||
* AUTHOR: Marcin O'BenY Benka <obeny@obeny.net>
|
||||
* VERSION: 1.0 (20091116)
|
||||
*
|
||||
* DESCRIPTION: Simple EEPROM (type 27C256) emulator, compatible with
|
||||
* Xtronics ROMulator protocol. This device allows to
|
||||
* perform Real Time Programming of Honda's OBD1 ECU during
|
||||
* tuning process.
|
||||
**************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* NOTE:
|
||||
*
|
||||
* Hardware configuration definitions.
|
||||
**************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include <avr/version.h>
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* CPU frequency */
|
||||
#define F_CPU 14745600UL
|
||||
|
||||
/* IO */
|
||||
/* address bus */
|
||||
#define ADDRESS PORTA
|
||||
#define ADDRESS_DDR DDRA
|
||||
|
||||
/* data bus */
|
||||
#define DATA_DDR DDRC
|
||||
#define DATA_IN PINC
|
||||
#define DATA_OUT PORTC
|
||||
#define DATA_PULLUP PORTC
|
||||
|
||||
/* signals mapping */
|
||||
#define RAMOE PD2 /* pin 11: ROM outputs enable; low active */
|
||||
#define RAMOE_ACT false
|
||||
#define RAMOE_PORT PORTD
|
||||
|
||||
#define LED_R PD3 /* pin 12: LED1 enable; low active */
|
||||
#define LED_R_ACT false
|
||||
#define LED_R_PORT PORTD
|
||||
|
||||
#define LED_G PD4 /* pin 13: LED2 enable; low active */
|
||||
#define LED_G_ACT false
|
||||
#define LED_G_PORT PORTD
|
||||
|
||||
#define ADRHI PD5 /* pin 14: address hi byte latch enable; low - latched */
|
||||
#define ADRHI_ACT false
|
||||
#define ADRHI_PORT PORTD
|
||||
|
||||
#define ADRLO PD6 /* pin 15: address lo byte latch enable; low - latched */
|
||||
#define ADRLO_ACT false
|
||||
#define ADRLO_PORT PORTD
|
||||
|
||||
#define DATDDIR PD7 /* pin 16: data direction; low - read, high - write */
|
||||
#define DATDDIR_READ false
|
||||
#define DATDDIR_WRITE true
|
||||
#define DATDDIR_PORT PORTD
|
||||
|
||||
#define RAMWE PB0 /* pin 40: RAM write enable; low active */
|
||||
#define RAMWE_ACT false
|
||||
#define RAMWE_PORT PORTB
|
||||
|
||||
#define ADRSOE PB1 /* pin 41: ECU socket address outputs enable; low active */
|
||||
#define ADRSOE_ACT false
|
||||
#define ADRSOE_PORT PORTB
|
||||
|
||||
#define DATDOE PB2 /* pin 42: uC data outputs enable; low active */
|
||||
#define DATDOE_ACT false
|
||||
#define DATDOE_PORT PORTB
|
||||
|
||||
#define DATSOE PB3 /* pin 43: ECU socket data outputs enable; low active*/
|
||||
#define DATSOE_ACT false
|
||||
#define DATSOE_PORT PORTB
|
||||
|
||||
#define ADRLOE PB4 /* pin 44: uC address latches output enable; low active */
|
||||
#define ADRLOE_ACT false
|
||||
#define ADRLOE_PORT PORTB
|
||||
|
||||
/* USART */
|
||||
#define USART_RBUF_SIZE 64
|
||||
#define USART_TBUF_SIZE 16
|
||||
#define USART_SEND_MAX_LENGTH 262
|
||||
#define USART_USE_STATUS
|
||||
#define USART_USE_TIMER
|
||||
|
||||
/* SYNC TIMER */
|
||||
#define SYNC_TIMER_COUNT 9
|
||||
#define SYNC_TIMER_PRESCALER 64
|
||||
#define SYNC_TIMER_PRESCALER_EDGE
|
||||
#define SYNC_TIMER_PRESCALER_OCR 255
|
||||
|
||||
/* MISC */
|
||||
#define MEMORY_SIZE 32768
|
||||
#define MEMORY_WRITE_RETRIES 3
|
||||
|
||||
#define FIRMWARE_VERSION FVERSION
|
||||
|
||||
#define ROMULATOR_PROTOCOL_ID 0x31
|
||||
#define ROMULATOR_PROTOCOL_MAJOR 0x01
|
||||
#define ROMULATOR_PROTOCOL_MINOR 0x28
|
||||
#define ROMULATOR_PROTOCOL_WRITE_RETRIES 3
|
||||
#define ROMULATOR_PROTOCOL_READ_TIMEOUT 5
|
||||
|
||||
|
||||
#endif /* _CONFIG_H */
|
||||
/* END */
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef _GLOBAL_H
|
||||
#define _GLOBAL_H
|
||||
|
||||
/**************************************************************************
|
||||
* Written by Marcin O'BenY Benka <obeny@obeny.net>
|
||||
* Version 1.4 (20091114)
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* Globaly used macros and type definitions.
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* type definitions */
|
||||
typedef uint8_t BYTE;
|
||||
typedef bool BOOL;
|
||||
|
||||
typedef int8_t INT8;
|
||||
typedef int16_t INT16;
|
||||
typedef int32_t INT32;
|
||||
|
||||
typedef uint8_t UINT8;
|
||||
typedef uint16_t UINT16;
|
||||
typedef uint32_t UINT32;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* MACROS
|
||||
***************************************************************************/
|
||||
|
||||
/* bit manipulation */
|
||||
#define BV(bit) (1 << (bit))
|
||||
|
||||
/* free pointer and set it to NULL */
|
||||
#define FREE(ptr) { if (ptr) { free(ptr); ptr = NULL; } }
|
||||
|
||||
/* convert value to bool */
|
||||
#define TO_BOOL(val) (!(!val))
|
||||
|
||||
/* set given bit of byte to 1 */
|
||||
#define sbi(byte, bit) (byte) |= (BV(bit))
|
||||
|
||||
/* set given bit of byte to 0 */
|
||||
#define cbi(byte, bit) (byte) &= ~(BV(bit))
|
||||
|
||||
/* read bit from value */
|
||||
#define GET_BIT(value, bit_n) (TO_BOOL((value) & (BV(bit_n))))
|
||||
|
||||
/* set bit in value */
|
||||
#define SET_BIT(value, bit_n, bool_val) ((bool_val)?(sbi(value, bit_n)):(cbi(value, bit_n)))
|
||||
|
||||
/* change state of bit to opposite in value */
|
||||
#define TOGGLE_BIT(value, bit_n) (value ^= BV(bit_n))
|
||||
|
||||
/* do a short delay using NOP instruction */
|
||||
#define NOP_DELAY __asm__ __volatile__("nop"::)
|
||||
|
||||
#endif /* _GLOBAL_H */
|
||||
/* END */
|
|
@ -0,0 +1,73 @@
|
|||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void initIoPorts()
|
||||
{
|
||||
/* set ports direction */
|
||||
ADDRESS_DDR = PORT_DIR_OUT;
|
||||
DATA_DDR = PORT_DIR_OUT;
|
||||
|
||||
/* initialize control pins */
|
||||
/* port B */
|
||||
SET_BIT(DDRB, RAMWE, PIN_DIR_OUT);
|
||||
SET_BIT(DDRB, ADRSOE, PIN_DIR_OUT);
|
||||
SET_BIT(DDRB, DATDOE, PIN_DIR_OUT);
|
||||
SET_BIT(DDRB, DATSOE, PIN_DIR_OUT);
|
||||
SET_BIT(DDRB, ADRLOE, PIN_DIR_OUT);
|
||||
/* port D */
|
||||
SET_BIT(DDRD, RAMOE, PIN_DIR_OUT);
|
||||
SET_BIT(DDRD, LED_R, PIN_DIR_OUT);
|
||||
SET_BIT(DDRD, LED_G, PIN_DIR_OUT);
|
||||
SET_BIT(DDRD, ADRHI, PIN_DIR_OUT);
|
||||
SET_BIT(DDRD, ADRLO, PIN_DIR_OUT);
|
||||
SET_BIT(DDRD, DATDDIR, PIN_DIR_OUT);
|
||||
|
||||
/* enable leds */
|
||||
SET_BIT(LED_R_PORT, LED_R, LED_R_ACT);
|
||||
SET_BIT(LED_G_PORT, LED_G, LED_G_ACT);
|
||||
|
||||
/* set default outputs state - deny any operation to SRAM */
|
||||
ADDRESS = 0x00;
|
||||
DATA_OUT = 0x00;
|
||||
|
||||
SET_BIT(RAMOE_PORT, RAMOE, !RAMOE_ACT);
|
||||
SET_BIT(RAMWE_PORT, RAMWE, !RAMWE_ACT);
|
||||
|
||||
SET_BIT(ADRHI_PORT, ADRHI, !ADRHI_ACT);
|
||||
SET_BIT(ADRLO_PORT, ADRLO, !ADRLO_ACT);
|
||||
|
||||
SET_BIT(ADRLOE_PORT, ADRLOE, !ADRLOE_ACT);
|
||||
SET_BIT(ADRSOE_PORT, ADRSOE, !ADRSOE_ACT);
|
||||
|
||||
SET_BIT(DATSOE_PORT, DATSOE, !DATSOE_ACT);
|
||||
SET_BIT(DATDOE_PORT, DATDOE, !DATDOE_ACT);
|
||||
|
||||
SET_BIT(DATDDIR_PORT, DATDDIR, DATDDIR_READ);
|
||||
|
||||
/* prevent from activating pull-ups */
|
||||
sbi(SFIOR, PUD);
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef _IO_H
|
||||
#define _IO_H
|
||||
|
||||
/**************************************************************************
|
||||
* Written by Marcin O'BenY Benka <obeny@obeny.net>
|
||||
* Version 1.4 (20091116)
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* Collection of basic I/O routines and definitions.
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
#define PORT_DIR_IN 0x00
|
||||
#define PORT_DIR_OUT 0xFF
|
||||
#define PORT_PULLUP_ACT 0xFF
|
||||
|
||||
#define PIN_DIR_IN false
|
||||
#define PIN_DIR_OUT true
|
||||
#define PIN_PULLUP_ACT true
|
||||
#define PIN_PULLUP_NACT false
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* initialization of I/O ports */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void initIoPorts();
|
||||
|
||||
|
||||
#endif /* _IO_H */
|
||||
/* END */
|
|
@ -0,0 +1,134 @@
|
|||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "comm.h"
|
||||
#include "io.h"
|
||||
#include "main.h"
|
||||
#include "memory.h"
|
||||
#include "sync_timer.h"
|
||||
#include "usart.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
int main()
|
||||
{
|
||||
UINT8 ui8_sync_timer_10 = 0;
|
||||
UINT8 ui8_sync_timer_100 = 0;
|
||||
|
||||
/* do initialization - both leds light*/
|
||||
init();
|
||||
|
||||
/* test memory and exit if write operation failed */
|
||||
if (!memoryTest())
|
||||
{
|
||||
SET_BIT(LED_G_PORT, LED_G, !LED_G_ACT);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* set default state of all cells to 0xFF */
|
||||
if (!memoryClear())
|
||||
{
|
||||
SET_BIT(LED_G_PORT, LED_G, !LED_G_ACT);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* if tests passed ok then, only green led blinks */
|
||||
SET_BIT(LED_R_PORT, LED_R, !LED_R_ACT);
|
||||
b_status_ready = true;
|
||||
|
||||
/* set default state to: read by ECU available */
|
||||
setMemoryAccessEcuRead();
|
||||
|
||||
/* start infinite loop */
|
||||
while (1)
|
||||
{
|
||||
/* code execuded 100 times a second */
|
||||
if (sync())
|
||||
{
|
||||
exec100();
|
||||
|
||||
ui8_sync_timer_10++;
|
||||
|
||||
/* code executed 10 times a second */
|
||||
if (ui8_sync_timer_10 == 10)
|
||||
{
|
||||
exec10();
|
||||
|
||||
ui8_sync_timer_10 = 0;
|
||||
ui8_sync_timer_100++;
|
||||
|
||||
/* code executed once a second */
|
||||
if (ui8_sync_timer_100 == 10)
|
||||
{
|
||||
exec1();
|
||||
|
||||
ui8_sync_timer_100 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* code executed in each pass */
|
||||
exec();
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void init()
|
||||
{
|
||||
/* initialize peripherials */
|
||||
initIoPorts();
|
||||
initSyncTimer();
|
||||
|
||||
/* default settings supported by CROME 1.5.3 and above */
|
||||
initUsart(USART_BAUD_920000, false, true, USART_PARITY_EVEN);
|
||||
|
||||
/* enable interrupts */
|
||||
sei();
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void exec()
|
||||
{
|
||||
if (usartUnreadBytes())
|
||||
pcCommand();
|
||||
|
||||
setMemoryAccessEcuRead();
|
||||
b_status_ready = true;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void exec1()
|
||||
{
|
||||
TOGGLE_BIT(LED_G_PORT, LED_G);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void exec10()
|
||||
{
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void exec100()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef _MAIN_H
|
||||
#define _MAIN_H
|
||||
|
||||
/**************************************************************************
|
||||
* Written by Marcin O'BenY Benka <obeny@obeny.net>
|
||||
* Version 1.0 (20091116)
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* Program entry point and related functions.
|
||||
**************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* initialize microcontroller */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void init();
|
||||
|
||||
/* executed on each mail loop pass */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void exec();
|
||||
|
||||
/* executed once a second */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void exec1();
|
||||
|
||||
/* executed each 1/10 of second */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void exec10();
|
||||
|
||||
/* executed each 1/100 of second */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void exec100();
|
||||
|
||||
|
||||
#endif /* _COMM_H */
|
||||
/* END */
|
|
@ -0,0 +1,295 @@
|
|||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "global.h"
|
||||
#include "io.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* GLOBAL: data send/receive buffer for communication with PC */
|
||||
BYTE data_buffer[262];
|
||||
|
||||
/* indicates whether device is accessible for ECU */
|
||||
static BOOL b_ecu_read_avail = false;
|
||||
|
||||
/* data byte used commonly in read/write and test operations */
|
||||
static BYTE data_byte;
|
||||
|
||||
/* indexing variable for memory operations */
|
||||
static UINT16 index = 0;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BOOL memoryClear()
|
||||
{
|
||||
/* default state for eeproms is 0xFF for each byte */
|
||||
data_byte = 0xFF;
|
||||
|
||||
for (index = 0; index < MEMORY_SIZE; ++index)
|
||||
{
|
||||
if (!memoryWrite(index, data_byte))
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BOOL memoryTest()
|
||||
{
|
||||
/* patterns testing */
|
||||
data_byte = 0x00;
|
||||
|
||||
/* TEST1: 0x00 pattern */
|
||||
for (index = 0; index < MEMORY_SIZE; ++index)
|
||||
memoryWrite(index, data_byte);
|
||||
|
||||
for (index = 0; index < MEMORY_SIZE; ++index)
|
||||
{
|
||||
if (*(memoryRead(index)) != 0x00)
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* TEST2: 0x55 odd and 0xAA even pattern */
|
||||
for (index = 0; index < MEMORY_SIZE; ++index)
|
||||
{
|
||||
if ((index & 1) == 0)
|
||||
data_byte = 0x55;
|
||||
else
|
||||
data_byte = 0xAA;
|
||||
|
||||
if (!memoryWrite(index, data_byte))
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* read from memory for verification */
|
||||
for (index = 0; index < MEMORY_SIZE; ++index)
|
||||
{
|
||||
data_byte = *(memoryRead(index));
|
||||
|
||||
if ((index & 1) == 0)
|
||||
{
|
||||
if (data_byte != 0x55)
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data_byte != 0xAA)
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* TEST3: 0xAA odd and 0x55 even pattern */
|
||||
for (index = 0; index < MEMORY_SIZE; ++index)
|
||||
{
|
||||
if ((index & 1) == 0)
|
||||
data_byte = 0xAA;
|
||||
else
|
||||
data_byte = 0x55;
|
||||
|
||||
if (!memoryWrite(index, data_byte))
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* read from memory for verification */
|
||||
for (index = 0; index < MEMORY_SIZE; ++index)
|
||||
{
|
||||
data_byte = *(memoryRead(index));
|
||||
|
||||
if ((index & 1) == 0)
|
||||
{
|
||||
if (data_byte != 0xAA)
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data_byte != 0x55)
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BOOL memoryWrite(const UINT16 addr, const BYTE byte)
|
||||
{
|
||||
static BYTE vrfy_byte;
|
||||
|
||||
for (UINT8 retry = 0; retry < MEMORY_WRITE_RETRIES; ++retry)
|
||||
{
|
||||
setMemoryAccessMcuWrite();
|
||||
setMemoryAddress(addr);
|
||||
|
||||
DATA_OUT = byte;
|
||||
|
||||
/* write to memory */
|
||||
SET_BIT(RAMWE_PORT, RAMWE, RAMWE_ACT);
|
||||
NOP_DELAY;
|
||||
SET_BIT(RAMWE_PORT, RAMWE, !RAMWE_ACT);
|
||||
|
||||
/* read byte from memory and check wheter written byte match */
|
||||
vrfy_byte = *(memoryRead(addr));
|
||||
|
||||
if (byte == vrfy_byte)
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* if something went bad, light red led */
|
||||
SET_BIT(LED_R_PORT, LED_R, LED_R_ACT);
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BOOL memoryWriteBlock(const UINT16 addr, const UINT16 size, const BYTE* buffer)
|
||||
{
|
||||
for (index = 0; index < size; ++index)
|
||||
{
|
||||
if (!memoryWrite((addr + index), *(buffer + index)))
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BYTE* memoryRead(const UINT16 addr)
|
||||
{
|
||||
static BYTE byte;
|
||||
|
||||
setMemoryAccessMcuRead();
|
||||
setMemoryAddress(addr);
|
||||
|
||||
byte = DATA_IN;
|
||||
|
||||
return (&byte);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BYTE* memoryReadBlock(const UINT16 addr, const UINT16 size, BYTE* buffer)
|
||||
{
|
||||
for (index = 0; index < size; ++index)
|
||||
*(buffer + index) = *(memoryRead(addr + index));
|
||||
|
||||
return (buffer);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void setMemoryAccessEcuRead()
|
||||
{
|
||||
if (b_ecu_read_avail)
|
||||
return;
|
||||
|
||||
SET_BIT(RAMOE_PORT, RAMOE, RAMOE_ACT);
|
||||
SET_BIT(RAMWE_PORT, RAMWE, !RAMWE_ACT);
|
||||
|
||||
SET_BIT(ADRHI_PORT, ADRHI, !ADRHI_ACT);
|
||||
SET_BIT(ADRLO_PORT, ADRLO, !ADRLO_ACT);
|
||||
|
||||
SET_BIT(ADRLOE_PORT, ADRLOE, !ADRLOE_ACT);
|
||||
SET_BIT(ADRSOE_PORT, ADRSOE, ADRSOE_ACT);
|
||||
|
||||
SET_BIT(DATSOE_PORT, DATSOE, DATSOE_ACT);
|
||||
SET_BIT(DATDOE_PORT, DATDOE, !DATDOE_ACT);
|
||||
|
||||
SET_BIT(DATDDIR_PORT, DATDDIR, DATDDIR_READ);
|
||||
|
||||
b_ecu_read_avail = true;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void setMemoryAccessMcuRead()
|
||||
{
|
||||
b_ecu_read_avail = false;
|
||||
|
||||
SET_BIT(RAMOE_PORT, RAMOE, RAMOE_ACT);
|
||||
SET_BIT(RAMWE_PORT, RAMWE, !RAMWE_ACT);
|
||||
|
||||
SET_BIT(ADRHI_PORT, ADRHI, !ADRHI_ACT);
|
||||
SET_BIT(ADRLO_PORT, ADRLO, !ADRLO_ACT);
|
||||
|
||||
SET_BIT(ADRLOE_PORT, ADRLOE, ADRLOE_ACT);
|
||||
SET_BIT(ADRSOE_PORT, ADRSOE, !ADRSOE_ACT);
|
||||
|
||||
SET_BIT(DATSOE_PORT, DATSOE, !DATSOE_ACT);
|
||||
SET_BIT(DATDOE_PORT, DATDOE, DATDOE_ACT);
|
||||
|
||||
SET_BIT(DATDDIR_PORT, DATDDIR, DATDDIR_READ);
|
||||
|
||||
DATA_DDR = PORT_DIR_IN;
|
||||
|
||||
/* ensure that pull-ups are disabled */
|
||||
DATA_PULLUP = (BYTE)~PORT_PULLUP_ACT;
|
||||
|
||||
/* wait for data propagation */
|
||||
NOP_DELAY;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void setMemoryAccessMcuWrite()
|
||||
{
|
||||
b_ecu_read_avail = false;
|
||||
|
||||
SET_BIT(RAMOE_PORT, RAMOE, !RAMOE_ACT);
|
||||
SET_BIT(RAMWE_PORT, RAMWE, !RAMWE_ACT);
|
||||
|
||||
SET_BIT(ADRHI_PORT, ADRHI, !ADRHI_ACT);
|
||||
SET_BIT(ADRLO_PORT, ADRLO, !ADRLO_ACT);
|
||||
|
||||
SET_BIT(ADRLOE_PORT, ADRLOE, ADRLOE_ACT);
|
||||
SET_BIT(ADRSOE_PORT, ADRSOE, !ADRSOE_ACT);
|
||||
|
||||
SET_BIT(DATSOE_PORT, DATSOE, !DATSOE_ACT);
|
||||
SET_BIT(DATDOE_PORT, DATDOE, DATDOE_ACT);
|
||||
|
||||
SET_BIT(DATDDIR_PORT, DATDDIR, DATDDIR_WRITE);
|
||||
|
||||
DATA_DDR = PORT_DIR_OUT;
|
||||
|
||||
/* wait for data propagation */
|
||||
NOP_DELAY;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void setMemoryAddress(const UINT16 addr)
|
||||
{
|
||||
/* set lo byte of address and wait for propagation before latching */
|
||||
ADDRESS = addr;
|
||||
SET_BIT(ADRLO_PORT, ADRLO, !ADRLO_ACT);
|
||||
NOP_DELAY;
|
||||
SET_BIT(ADRLO_PORT, ADRLO, ADRLO_ACT);
|
||||
NOP_DELAY;
|
||||
|
||||
/* the same with hi byte of address */
|
||||
ADDRESS = (addr >> 8);
|
||||
SET_BIT(ADRHI_PORT, ADRHI, !ADRHI_ACT);
|
||||
NOP_DELAY;
|
||||
SET_BIT(ADRHI_PORT, ADRHI, ADRHI_ACT);
|
||||
NOP_DELAY;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
|
@ -0,0 +1,109 @@
|
|||
#ifndef _MEMORY_H
|
||||
#define _MEMORY_H
|
||||
|
||||
/**************************************************************************
|
||||
* Written by Marcin O'BenY Benka <obeny@obeny.net>
|
||||
* Version 1.1 (20091124)
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* Operations on volatile SRAM memory.
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* GLOBAL: data send/receive buffer for communication with PC */
|
||||
extern BYTE data_buffer[262];
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* clear whole memory, writting 0x00 to each cell */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : TRUE on success, FALSE on fail
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
BOOL memoryClear();
|
||||
|
||||
/* test SRAM memory, writting different patterns */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : TRUE on success, FALSE on fail
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
BOOL memoryTest();
|
||||
|
||||
/* write byte to memory */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : TRUE on success, FALSE on fail
|
||||
ARGS : addr - address in memory matrix
|
||||
byte - byte to write to memory
|
||||
* ----------------------------------------------------------------------- */
|
||||
BOOL memoryWrite(const UINT16 addr, const BYTE byte);
|
||||
|
||||
/* write block of data to memory */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : TRUE on success, FALSE on fail
|
||||
ARGS : addr - address of first byte in memory matrix
|
||||
size - bytes number to write to memory
|
||||
buffer - pointer to data buffer with data to write
|
||||
* ----------------------------------------------------------------------- */
|
||||
BOOL memoryWriteBlock(const UINT16 addr, const UINT16 size, const BYTE* buffer);
|
||||
|
||||
/* read byte from memory */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : pointer to byte read
|
||||
ARGS : addr - address in memory matrix
|
||||
* ----------------------------------------------------------------------- */
|
||||
BYTE* memoryRead(const UINT16 addr);
|
||||
|
||||
/* read block of data from memory */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : pointer to data read
|
||||
ARGS : addr - address of first byte in memory matrix
|
||||
size - bytes number to read from memory
|
||||
buffer - pointer to buffer where data will be written
|
||||
* ----------------------------------------------------------------------- */
|
||||
BYTE* memoryReadBlock(const UINT16 addr, const UINT16 size, BYTE* buffer);
|
||||
|
||||
/* enable ECU to read from memory */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void setMemoryAccessEcuRead();
|
||||
|
||||
/* enable MCU to read from memory */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void setMemoryAccessMcuRead();
|
||||
|
||||
/* enable MCU to write to memory */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void setMemoryAccessMcuWrite();
|
||||
|
||||
/* set memory address */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void setMemoryAddress(const UINT16 addr);
|
||||
|
||||
|
||||
#endif /* _MEMORY_H */
|
||||
/* END */
|
|
@ -0,0 +1,125 @@
|
|||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "sync_timer.h"
|
||||
#include "usart.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* overflow counter */
|
||||
static volatile UINT8 ui8_sync_timer_overflow = 0;
|
||||
|
||||
/* flag that is set 100 per second */
|
||||
static volatile BOOL b_100 = false;
|
||||
|
||||
/* TIMER0 compare interrupt handler */
|
||||
ISR(TIMER0_COMP_vect)
|
||||
{
|
||||
++ui8_sync_timer_overflow;
|
||||
|
||||
if (ui8_sync_timer_overflow == SYNC_TIMER_COUNT)
|
||||
{
|
||||
ui8_sync_timer_overflow = 0;
|
||||
b_100 = true;
|
||||
|
||||
#ifdef USART_USE_TIMER
|
||||
/* used by usartRead for timeout */
|
||||
++usart_timeout;
|
||||
#endif /* USART USE_TIMER */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
inline BOOL sync()
|
||||
{
|
||||
if (b_100)
|
||||
{
|
||||
b_100 = false;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void initSyncTimer()
|
||||
{
|
||||
/* set counter0 value */
|
||||
OCR0 = SYNC_TIMER_PRESCALER_OCR;
|
||||
|
||||
/* enable counter0 interrupt */
|
||||
TIMSK = BV(OCIE0);
|
||||
|
||||
/* enable counter0 compare */
|
||||
TCCR0 = BV(WGM01);
|
||||
|
||||
#ifdef SYNC_TIMER_PRESCALER_EDGE
|
||||
/* prescaler <= fcpu/1 */
|
||||
#if SYNC_TIMER_PRESCALER == 1
|
||||
TCCR0 |= BV(CS00);
|
||||
/* prescaler <= fcpu/8 */
|
||||
#elif SYNC_TIMER_PRESCALER == 8
|
||||
TCCR0 |= BV(CS01);
|
||||
/* prescaler <= fcpu/64 */
|
||||
#elif SYNC_TIMER_PRESCALER == 64
|
||||
TCCR0 |= BV(CS00) | BV(CS01);
|
||||
/* prescaler <= fcpu/256 */
|
||||
#elif SYNC_TIMER_PRESCALER == 256
|
||||
TCCR0 |= BV(CS02);
|
||||
/* prescaler <= fcpu/1024 */
|
||||
#elif SYNC_TIMER_PRESCALER == 1024
|
||||
TCCR0 |= BV(CS00) | BV(CS02);
|
||||
#else
|
||||
#error "SYNC_TIMER: SYNC_TIMER_PRESCALER not set"
|
||||
#endif /* SYNC_TIMER_PRESCALER */
|
||||
#else
|
||||
/* prescaler <= fcpu/1 */
|
||||
#if SYNC_TIMER_PRESCALER == 1
|
||||
TCCR0 |= BV(CS00);
|
||||
/* prescaler <= fcpu/8 */
|
||||
#elif SYNC_TIMER_PRESCALER == 8
|
||||
TCCR0 |= BV(CS01);
|
||||
/* prescaler <= fcpu/32 */
|
||||
#elif SYNC_TIMER_PRESCALER == 32
|
||||
TCCR0 |= BV(CS00) | BV(CS01);
|
||||
/* prescaler <= fcpu/64 */
|
||||
#elif SYNC_TIMER_PRESCALER == 64
|
||||
TCCR0 |= BV(CS02);
|
||||
/* prescaler <= fcpu/128 */
|
||||
#elif SYNC_TIMER_PRESCALER == 128
|
||||
TCCR0 |= BV(CS00) | BV(CS02);
|
||||
/* prescaler <= fcpu/8 */
|
||||
#elif SYNC_TIMER_PRESCALER == 256
|
||||
TCCR0 |= BV(CS01) | BV(CS02);
|
||||
/* prescaler <= fcpu/8 */
|
||||
#elif SYNC_TIMER_PRESCALER == 1024
|
||||
TCCR0 |= BV(CS00) | BV(CS01) | BV(CS02);
|
||||
/* prescaler not set */
|
||||
#else
|
||||
#error "SYNC_TIMER: SYNC_TIMER_PRESCALER not set"
|
||||
#endif /* SYNC_TIMER_PRESCALER */
|
||||
#endif /* SYNC_TIMER_PRESCALER_EDGE */
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef _SYNC_TIMER_H
|
||||
#define _SYNC_TIMER_H
|
||||
|
||||
/**************************************************************************
|
||||
* Written by Marcin O'BenY Benka <obeny@obeny.net>
|
||||
* Version 1.5 (20100225)
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* Timer for main event loop synchronization.
|
||||
* sync ticks presents following equotation:
|
||||
* sync = fcpu/(SYNC_TIMER_PRESCALER*SYNC_TIMER_PRESCALER_OCR*SYNC_TIMER_COUNT)
|
||||
* sync value should give execution each 1/100 of second.
|
||||
*
|
||||
* IMPORTANT:
|
||||
* This library need to set following constants to work:
|
||||
* - SYNC_TIMER_COUNT - additional divider for reaching desired sync times
|
||||
* - SYNC_TIMER_PRESCALER - value to divide fcpu signal for timer
|
||||
* supported values: 1, 8, 32, 64, 128, 256 and 1024
|
||||
* - SYNC_TIMER_PRESCALER_OCR - max value for counter
|
||||
* - SYNC_TIMER_PRESCALER_EDGE - set it for MCUs that sets
|
||||
* edge reaction via CSXX bits.
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* tells whether 1/100 of second expired */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : TRUE if 10ms from previous execution elapsed, FALSE otherwise
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
BOOL sync();
|
||||
|
||||
/* initialization of timer */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void initSyncTimer();
|
||||
|
||||
|
||||
#endif /* _SYNC_TIMER_H */
|
||||
/* END */
|
|
@ -0,0 +1,366 @@
|
|||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "usart.h"
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* check for receive/transmit buffer size */
|
||||
#if (USART_RBUF_SIZE >= 0xFF | USART_TBUF_SIZE >= 0xFF)
|
||||
#error "USART: buffers too big (max = 256 bytes)"
|
||||
#endif
|
||||
|
||||
#if (USART_RBUF_SIZE & USART_RMASK)
|
||||
#error "USART: RX buffer size is not power of 2"
|
||||
#endif
|
||||
|
||||
#if (USART_TBUF_SIZE & USART_TMASK)
|
||||
#error "USART: TX buffer size is not power of 2"
|
||||
#endif
|
||||
|
||||
/* transmission buffers */
|
||||
static volatile BYTE rx_buff[USART_RBUF_SIZE];
|
||||
static volatile BYTE tx_buff[USART_TBUF_SIZE];
|
||||
|
||||
/* buffer indexes */
|
||||
static volatile UINT8 rx_head, rx_tail;
|
||||
static volatile UINT8 tx_head, tx_tail;
|
||||
|
||||
/* usart status */
|
||||
static volatile e_usartstatus_t usartstatus;
|
||||
|
||||
#ifdef USART_USE_TIMER
|
||||
/* timeout counter for read timeout */
|
||||
volatile UINT16 usart_timeout = 0;
|
||||
#endif /* USART_USE_TIMER */
|
||||
|
||||
/* incoming byte interrupt handler */
|
||||
ISR (USART_INT_RX)
|
||||
{
|
||||
#ifdef USART_USE_STATUS
|
||||
/* set status of received byte */
|
||||
if (USART_UCSRA & BV(FE))
|
||||
sbi(usartstatus, RX_STAT_FE);
|
||||
if (USART_UCSRA & BV(DOR))
|
||||
sbi(usartstatus, RX_STAT_DOR);
|
||||
/* Atmegas have different name of this flag */
|
||||
#ifdef UPE
|
||||
if (USART_UCSRA & BV(UPE))
|
||||
sbi(usartstatus, RX_STAT_PE);
|
||||
#else
|
||||
if (USART_UCSRA & BV(PE))
|
||||
sbi(usartstatus, RX_STAT_PE);
|
||||
#endif /* UPE */
|
||||
#endif /* USART_USE_STATUS */
|
||||
|
||||
/* discard last byte in buffer if buffer overflow occured */
|
||||
if (usartstatus & RX_OVR)
|
||||
rx_tail = (rx_tail + 1) & USART_RMASK;
|
||||
|
||||
/* insert byte to ring buffer */
|
||||
rx_buff[rx_head] = USART_UDR;
|
||||
rx_head = (rx_head + 1) & USART_RMASK;
|
||||
|
||||
/* indicate buffer overflow */
|
||||
if (rx_head == rx_tail)
|
||||
sbi(usartstatus, RX_STAT_OVR);
|
||||
}
|
||||
|
||||
/* outgoing byte interrupt handler */
|
||||
ISR (USART_INT_UDRE)
|
||||
{
|
||||
if ((tx_tail != tx_head) || (usartstatus & TX_FULL))
|
||||
{
|
||||
USART_UDR = tx_buff[tx_tail];
|
||||
tx_tail = (tx_tail + 1) & USART_TMASK;
|
||||
|
||||
cbi(usartstatus, TX_STAT_FULL);
|
||||
}
|
||||
else
|
||||
cbi(USART_UCSRB, USART_UDRIE);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BOOL usartReceiveBufferOverflow()
|
||||
{
|
||||
return (TO_BOOL((usartstatus & RX_OVR)));
|
||||
}
|
||||
|
||||
#ifndef USART_USE_TIMER
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BOOL usartRead(BYTE *str, const UINT16 count)
|
||||
{
|
||||
#ifdef USART_USE_STATUS
|
||||
static BOOL b_byte_read_ok;
|
||||
#endif /* USART_USE_STATUS */
|
||||
|
||||
for (UINT16 i = 0; i < count; ++i)
|
||||
{
|
||||
/* if any timeout is present, wait for incomming byte */
|
||||
while (!usartUnreadBytes());
|
||||
|
||||
#ifdef USART_USE_STATUS
|
||||
*str = usartReadByte(&b_byte_read_ok);
|
||||
#endif /* USART_USE_STATUS */
|
||||
++str;
|
||||
|
||||
#ifdef USART_USE_STATUS
|
||||
if (!b_byte_read_ok)
|
||||
return (false);
|
||||
#endif /* USART_USE_STATUS */
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
#else
|
||||
/* ----------------------------------------------------------------------- */
|
||||
BOOL usartRead(BYTE *str, const UINT16 count, const UINT16 timeout)
|
||||
{
|
||||
#ifdef USART_USE_STATUS
|
||||
static BOOL b_byte_read_ok;
|
||||
#endif /* USART_USE_STATUS */
|
||||
|
||||
for (UINT16 i = 0; i < count; ++i)
|
||||
{
|
||||
usart_timeout = 0;
|
||||
|
||||
/* if any timeout is present, wait for incomming byte */
|
||||
while (!usartUnreadBytes() && timeout)
|
||||
{
|
||||
if (usart_timeout == timeout)
|
||||
return (false);
|
||||
}
|
||||
|
||||
#ifdef USART_USE_STATUS
|
||||
*str = usartReadByte(&b_byte_read_ok);
|
||||
#endif /* USART_USE_STATUS */
|
||||
++str;
|
||||
#ifdef USART_USE_STATUS
|
||||
|
||||
if (!b_byte_read_ok)
|
||||
return (false);
|
||||
#endif /* USART_USE_STATUS */
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
#endif /* USART_USE_TIMER */
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
#ifdef USART_USE_STATUS
|
||||
BYTE usartReadByte(BOOL *ok)
|
||||
#else
|
||||
BYTE usartReadByte()
|
||||
#endif /* USART_USE_STATUS */
|
||||
{
|
||||
static BYTE b;
|
||||
|
||||
if (usartUnreadBytes())
|
||||
{
|
||||
b = rx_buff[rx_tail];
|
||||
rx_tail = (rx_tail + 1) & USART_RMASK;
|
||||
cbi(usartstatus, RX_STAT_OVR);
|
||||
|
||||
#ifdef USART_USE_STATUS
|
||||
if (ok)
|
||||
{
|
||||
if (usartstatus & (RX_FE | RX_PE | RX_DOR))
|
||||
{
|
||||
*ok = false;
|
||||
|
||||
/* clear error flags */
|
||||
cbi(usartstatus, RX_STAT_FE);
|
||||
cbi(usartstatus, RX_STAT_PE);
|
||||
cbi(usartstatus, RX_STAT_DOR);
|
||||
}
|
||||
else
|
||||
*ok = true;
|
||||
}
|
||||
|
||||
return (b);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ok)
|
||||
*ok = false;
|
||||
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
}
|
||||
return (b);
|
||||
#endif /* USART_USE_STATUS */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
UINT8 usartUnreadBytes()
|
||||
{
|
||||
if (usartstatus & RX_OVR)
|
||||
return (USART_RBUF_SIZE);
|
||||
if (rx_head > rx_tail)
|
||||
return (rx_head - rx_tail);
|
||||
if (rx_head < rx_tail)
|
||||
return (USART_RBUF_SIZE - (rx_tail - rx_head));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void initUsart(const UINT16 baudrate, const BOOL double_speed, const BOOL two_stop_bits, const UINT8 parity)
|
||||
{
|
||||
UINT16 usart_const;
|
||||
UINT8 ucsrc;
|
||||
|
||||
float f_usart_const;
|
||||
|
||||
rx_head = 0;
|
||||
rx_tail = 0;
|
||||
tx_head = 0;
|
||||
tx_tail = 0;
|
||||
usartstatus = 0;
|
||||
|
||||
/* set speed */
|
||||
if (double_speed)
|
||||
{
|
||||
/* compute USART clock and round to nearest value */
|
||||
f_usart_const = (float)(USART_F_CPU) / (float)(8);
|
||||
f_usart_const /= (float)(baudrate);
|
||||
f_usart_const -= 1;
|
||||
|
||||
usart_const = (UINT16)(lrint(f_usart_const));
|
||||
USART_UCSRA = BV(UDRE) | BV(U2X);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* compute USART clock and round to nearest value */
|
||||
f_usart_const = (float)(USART_F_CPU) / (float)(16);
|
||||
f_usart_const /= (float)(baudrate);
|
||||
f_usart_const -= 1;
|
||||
|
||||
usart_const = (UINT16)(lrint(f_usart_const));
|
||||
USART_UCSRA = BV(UDRE);
|
||||
}
|
||||
USART_UBRRH = (UINT8)(usart_const >> 8);
|
||||
USART_UBRRL = (UINT8)usart_const;
|
||||
|
||||
/* set rx and tx enabled, allow interrupt on new byte received */
|
||||
USART_UCSRB = BV(RXEN) | BV(TXEN) | BV(RXCIE);
|
||||
|
||||
/* set frame format: asynchronous, 8bit data */
|
||||
ucsrc = BV(UCSZ0) | BV(UCSZ1);
|
||||
|
||||
/* set frame format: 2 stop bits */
|
||||
if (two_stop_bits)
|
||||
ucsrc |= BV(USBS);
|
||||
|
||||
/* set frame format: parity */
|
||||
if (parity == USART_PARITY_EVEN)
|
||||
ucsrc |= BV(UPM1);
|
||||
else if (parity == USART_PARITY_ODD)
|
||||
ucsrc |= BV(UPM0) | BV(UPM1);
|
||||
|
||||
/* URSEL for access to UCSRC insetad of UBRRH */
|
||||
#ifdef URSEL
|
||||
ucsrc |= BV(URSEL);
|
||||
#endif /* URSEL */
|
||||
|
||||
USART_UCSRC = ucsrc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void usartFlush()
|
||||
{
|
||||
rx_tail = rx_head;
|
||||
cbi(usartstatus, RX_STAT_OVR);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void usartSend(BYTE *str, const UINT16 length)
|
||||
{
|
||||
static UINT16 real_length;
|
||||
|
||||
/* compute max length of data to send */
|
||||
if (!length)
|
||||
real_length = USART_SEND_MAX_LENGTH;
|
||||
else
|
||||
real_length = (length > USART_SEND_MAX_LENGTH)?(USART_SEND_MAX_LENGTH):(length);
|
||||
|
||||
/* start sending data */
|
||||
for (UINT16 i = 0; i < real_length; ++i)
|
||||
{
|
||||
usartSendByte(*str);
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void usartSendByte(const BYTE b)
|
||||
{
|
||||
/* wait for free space in buffer */
|
||||
while (usartstatus & TX_FULL);
|
||||
|
||||
/* insert byte to transmit buffer */
|
||||
tx_buff[tx_head] = b;
|
||||
tx_head = (tx_head + 1) & USART_TMASK;
|
||||
|
||||
if (tx_head == tx_tail)
|
||||
sbi(usartstatus, TX_STAT_FULL);
|
||||
|
||||
sbi(USART_UCSRB, USART_UDRIE);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void usartSendString(BYTE *str, const UINT16 length)
|
||||
{
|
||||
static UINT16 real_length;
|
||||
|
||||
/* compute max length of data to send */
|
||||
if (!length)
|
||||
real_length = USART_SEND_MAX_LENGTH;
|
||||
else
|
||||
real_length = (length > USART_SEND_MAX_LENGTH)?(USART_SEND_MAX_LENGTH):(length);
|
||||
|
||||
/* start sending data */
|
||||
for (UINT16 i = 0; (i < real_length) && *str; ++i)
|
||||
{
|
||||
usartSendByte(*str);
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void usartSendString_P(const BYTE *str)
|
||||
{
|
||||
BYTE c;
|
||||
|
||||
while ((c = pgm_read_byte(str)))
|
||||
{
|
||||
usartSendByte(c);
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
|
@ -0,0 +1,269 @@
|
|||
#ifndef _USART_H
|
||||
#define _USART_H
|
||||
|
||||
/**************************************************************************
|
||||
* Written by Marcin O'BenY Benka <obeny@obeny.net>
|
||||
* Version 1.11 (20100224)
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* Buffered USART support.
|
||||
*
|
||||
* IMPORTANT:
|
||||
* This library needs to set following constants to work:
|
||||
* - F_CPU - cpu frequency
|
||||
* - USART_RBUF_SIZE - receive buffer size (only power of 2)
|
||||
* - USART_TBUF_SIZE - transmit buffer size (only power of 2)
|
||||
* - USART_SEND_MAX_LENGTH - max length of transmitted data block
|
||||
* - USART_USE_PORT1 - uses USART1 instead of USART0
|
||||
* - USART_USE_STATUS - uses status register for received data
|
||||
* - USART_USE_TIMER - enables support for timer-based read timeout
|
||||
**************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* INCLUDES
|
||||
***************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "global.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* configure first USART port */
|
||||
#ifndef USART_USE_PORT1
|
||||
/* for one USART port MCUs*/
|
||||
#ifdef UCSRA
|
||||
#define USART_UBRRH UBRRH
|
||||
#define USART_UBRRL UBRRL
|
||||
|
||||
#define USART_UCSRA UCSRA
|
||||
#define USART_UCSRB UCSRB
|
||||
#define USART_UCSRC UCSRC
|
||||
|
||||
#define USART_UDR UDR
|
||||
#define USART_UDRIE UDRIE
|
||||
|
||||
/* some Atmegas has got USART_RX_vect others USART_RXC_vect defined */
|
||||
#ifdef USART_RX_vect
|
||||
#define USART_INT_RX USART_RX_vect
|
||||
#else
|
||||
#define USART_INT_RX USART_RXC_vect
|
||||
#endif /* USART_RX_vect */
|
||||
#define USART_INT_UDRE USART_UDRE_vect
|
||||
/* for two USART ports MCUs*/
|
||||
#else
|
||||
#define USART_UBRRH UBRR0H
|
||||
#define USART_UBRRL UBRR0L
|
||||
|
||||
#define USART_UCSRA UCSR0A
|
||||
#define USART_UCSRB UCSR0B
|
||||
#define USART_UCSRC UCSR0C
|
||||
|
||||
#define USART_UDR UDR0
|
||||
#define USART_UDRIE UDRIE0
|
||||
|
||||
/* some Atmegas has got USART0_RX_vect others USART0_RXC_vect defined */
|
||||
#ifdef USART0_RX_vect
|
||||
#define USART_INT_RX USART0_RX_vect
|
||||
#else
|
||||
#define USART_INT_RX USART0_RXC_vect
|
||||
#endif /* USART_RX_vect */
|
||||
#define USART_INT_UDRE USART0_UDRE_vect
|
||||
#endif /* UCSRA */
|
||||
/* configure second USART port */
|
||||
#else
|
||||
#define USART_UBRRH UBRR1H
|
||||
#define USART_UBRRL UBRR1L
|
||||
|
||||
#define USART_UCSRA UCSR1A
|
||||
#define USART_UCSRB UCSR1B
|
||||
#define USART_UCSRC UCSR1C
|
||||
|
||||
#define USART_UDR UDR1
|
||||
#define USART_UDRIE UDRIE1
|
||||
|
||||
/* some Atmegas has got USART1_RX_vect others USART1_RXC_vect defined */
|
||||
#ifdef USART1_RX_vect
|
||||
#define USART_INT_RX USART1_RX_vect
|
||||
#else
|
||||
#define USART_INT_RX USART1_RXC_vect
|
||||
#endif /* USART_RX_vect */
|
||||
#define USART_INT_UDRE USART1_UDRE_vect
|
||||
#endif /* USART_USE_PORT1 */
|
||||
|
||||
/* cpu frequency divided by 100 used for initialization */
|
||||
#define USART_F_CPU (F_CPU/100)
|
||||
|
||||
/* buffers masks */
|
||||
/* NOTE: Works only for values that are power of 2. This is used for fast
|
||||
* modulo in circular transmit/receive buffer.
|
||||
*/
|
||||
#define USART_RMASK (USART_RBUF_SIZE-1)
|
||||
#define USART_TMASK (USART_TBUF_SIZE-1)
|
||||
|
||||
/* status bits */
|
||||
#define RX_STAT_DOR 3
|
||||
#define RX_STAT_FE 4
|
||||
#define RX_STAT_PE 2
|
||||
#define RX_STAT_OVR 1
|
||||
#define TX_STAT_FULL 0
|
||||
|
||||
/* usart baud rates */
|
||||
enum e_usartbaud
|
||||
{
|
||||
/* standard baudrates */
|
||||
USART_BAUD_9600 = 96,
|
||||
USART_BAUD_19200 = 192,
|
||||
USART_BAUD_38400 = 384,
|
||||
USART_BAUD_57600 = 576,
|
||||
USART_BAUD_115200 = 1152,
|
||||
USART_BAUD_230400 = 2304,
|
||||
USART_BAUD_460800 = 4608,
|
||||
USART_BAUD_921600 = 9216,
|
||||
|
||||
/* custom baudrates */
|
||||
USART_BAUD_460000 = 4600,
|
||||
USART_BAUD_920000 = 9200
|
||||
};
|
||||
typedef enum e_usartbaud e_usartbaud_t;
|
||||
|
||||
/* usart parity settings */
|
||||
enum e_usartparity
|
||||
{
|
||||
USART_PARITY_NONE = 0,
|
||||
USART_PARITY_EVEN = 1,
|
||||
USART_PARITY_ODD = 2
|
||||
};
|
||||
typedef enum e_usartparity e_usartparity_t;
|
||||
|
||||
/* usart status */
|
||||
enum e_usartstatus
|
||||
{
|
||||
RX_DOR = BV(RX_STAT_DOR), /* rx dataoverrun */
|
||||
RX_FE = BV(RX_STAT_FE), /* rx frame error */
|
||||
RX_PE = BV(RX_STAT_PE), /* rx parity error */
|
||||
RX_OVR = BV(RX_STAT_OVR), /* rx ring buffer overflow */
|
||||
TX_FULL = BV(TX_STAT_FULL) /* tx full buffer */
|
||||
};
|
||||
typedef enum e_usartstatus e_usartstatus_t;
|
||||
|
||||
#ifdef USART_USE_TIMER
|
||||
/* timeout counter (incremented in sync_timer) */
|
||||
extern volatile UINT16 usart_timeout;
|
||||
#endif /* USART_USE_TIMER */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* read bytes and write them to buffer */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : TRUE if receive buffer overflow occured, FALSE otherwise
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
BOOL usartReceiveBufferOverflow();
|
||||
|
||||
#ifndef USART_USE_TIMER
|
||||
/* read bytes and write them to buffer */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : pointer to buffer where data was written
|
||||
ARGS : str - pointer to buffer, where data will be written
|
||||
count - bytes to read
|
||||
NOTE : if USART_USE_TIMER isn't declared, function won't
|
||||
have timeout support
|
||||
* ----------------------------------------------------------------------- */
|
||||
BOOL usartRead(BYTE* str, const UINT16 count);
|
||||
|
||||
#else
|
||||
/* read bytes and write them to buffer */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : pointer to buffer where data was written
|
||||
ARGS : str - pointer to buffer, where data will be written
|
||||
count - bytes to read
|
||||
timeout - timeout in 1/100 of second (less then 65536)
|
||||
NOTE : if USART_USE_TIMER is declared, function will have
|
||||
timer-based timeout support enabled (see sync_timer.h)
|
||||
* ----------------------------------------------------------------------- */
|
||||
BOOL usartRead(BYTE* str, const UINT16 count, const UINT16 timeout);
|
||||
#endif /* USART_USE_TIMER */
|
||||
|
||||
#ifdef USART_USE_STATUS
|
||||
/* read next byte in buffer, be carefull for buffer overflow */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : read byte or 0 if buffer is empty
|
||||
ARGS : ok - TRUE on byte read, FALSE on fail
|
||||
* ----------------------------------------------------------------------- */
|
||||
BYTE usartReadByte(BOOL *ok);
|
||||
|
||||
#else
|
||||
/* read next byte in buffer, be carefull for buffer overflow */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : read byte or 0 if buffer is empty
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
BYTE usartReadByte();
|
||||
#endif /* USART_USE_STATUS */
|
||||
|
||||
/* unread bytes count */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : number of unread bytes in buffer
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
UINT8 usartUnreadBytes();
|
||||
|
||||
/* initialization of USART */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : baudrate - baudrate divided by 100 or value from e_usartbaud
|
||||
double_speed - enables usart double speed mode
|
||||
two_stop_bits - use two stop bits in frame
|
||||
parity - use parity checking - e_usartparity
|
||||
* ----------------------------------------------------------------------- */
|
||||
void initUsart(const UINT16 baudrate, const BOOL double_speed, const BOOL two_stop_bits, const UINT8 parity);
|
||||
|
||||
/* flush bytes waiting in receive buffer (ignore them) */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : NONE
|
||||
* ----------------------------------------------------------------------- */
|
||||
void usartFlush();
|
||||
|
||||
/* send data */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : str - string to be sent
|
||||
length - max length of given string
|
||||
(limited to USART_SEND_MAX_LENGTH)
|
||||
* ----------------------------------------------------------------------- */
|
||||
void usartSend(BYTE *str, const UINT16 length);
|
||||
|
||||
/* send single byte */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : b - byte to be transmitted
|
||||
* ----------------------------------------------------------------------- */
|
||||
void usartSendByte(const BYTE b);
|
||||
|
||||
/* send string */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : str - string to be sent
|
||||
length - max length of given string
|
||||
(limited to USART_SEND_MAX_LENGTH)
|
||||
* ----------------------------------------------------------------------- */
|
||||
void usartSendString(BYTE *str, const UINT16 length);
|
||||
|
||||
/* send string from program memory */
|
||||
/* -----------------------------------------------------------------------
|
||||
RETURN VAL : NONE
|
||||
ARGS : str - string to be sent
|
||||
* ----------------------------------------------------------------------- */
|
||||
void usartSendString_P(const BYTE *str);
|
||||
|
||||
|
||||
#endif /* _USART_H */
|
||||
/* END */
|
|
@ -0,0 +1,322 @@
|
|||
#! /usr/bin/perl -w
|
||||
|
||||
#
|
||||
# colorgcc
|
||||
#
|
||||
# Version: 1.3.2
|
||||
#
|
||||
# $Id: colorgcc,v 1.10 1999/04/29 17:15:52 jamoyers Exp $
|
||||
#
|
||||
# A wrapper to colorize the output from compilers whose messages
|
||||
# match the "gcc" format.
|
||||
#
|
||||
# Requires the ANSIColor module from CPAN.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# In a directory that occurs in your PATH _before_ the directory
|
||||
# where the compiler lives, create a softlink to colorgcc for
|
||||
# each compiler you want to colorize:
|
||||
#
|
||||
# g++ -> colorgcc
|
||||
# gcc -> colorgcc
|
||||
# cc -> colorgcc
|
||||
# etc.
|
||||
#
|
||||
# That's it. When "g++" is invoked, colorgcc is run instead.
|
||||
# colorgcc looks at the program name to figure out which compiler to run.
|
||||
#
|
||||
# The default settings can be overridden with ~/.colorgccrc.
|
||||
# See the comments in the sample .colorgccrc for more information.
|
||||
#
|
||||
# Note:
|
||||
#
|
||||
# colorgcc will only emit color codes if:
|
||||
#
|
||||
# (1) Its STDOUT is a tty and
|
||||
# (2) the value of $TERM is not listed in the "nocolor" option.
|
||||
#
|
||||
# If colorgcc colorizes the output, the compiler's STDERR will be
|
||||
# combined with STDOUT. Otherwise, colorgcc just passes the output from
|
||||
# the compiler through without modification.
|
||||
#
|
||||
# Author: Jamie Moyers <jmoyers@geeks.com>
|
||||
# Started: April 20, 1999
|
||||
# Licence: GNU Public License
|
||||
#
|
||||
# Credits:
|
||||
#
|
||||
# I got the idea for this from a script called "color_cvs":
|
||||
# color_cvs .03 Adrian Likins <adrian@gimp.org> <adrian@redhat.com>
|
||||
#
|
||||
# <seh4@ix.netcom.com> (Scott Harrington)
|
||||
# Much improved handling of compiler command line arguments.
|
||||
# exec compiler when not colorizing to preserve STDOUT, STDERR.
|
||||
# Fixed my STDIN kludge.
|
||||
#
|
||||
# <ecarotti@athena.polito.it> (Elias S. G. Carotti)
|
||||
# Corrected handling of text like -DPACKAGE=\"Package\"
|
||||
# Spotted return code bug.
|
||||
#
|
||||
# <erwin@erwin.andreasen.org> (Erwin S. Andreasen)
|
||||
# <schurchi@ucsd.edu> (Steve Churchill)
|
||||
# Return code bug fixes.
|
||||
#
|
||||
# <rik@kde.org> (Rik Hemsley)
|
||||
# Found STDIN bug.
|
||||
#
|
||||
# Changes:
|
||||
#
|
||||
# 1.3.2 Better handling of command line arguments to compiler.
|
||||
#
|
||||
# If we aren't colorizing output, we just exec the compiler which
|
||||
# preserves the original STDOUT and STDERR.
|
||||
#
|
||||
# Removed STDIN kludge. STDIN being passed correctly now.
|
||||
#
|
||||
# 1.3.1 Added kludge to copy STDIN to the compiler's STDIN.
|
||||
#
|
||||
# 1.3.0 Now correctly returns (I hope) the return code of the compiler
|
||||
# process as its own.
|
||||
#
|
||||
# 1.2.1 Applied patch to handle text similar to -DPACKAGE=\"Package\".
|
||||
#
|
||||
# 1.2.0 Added tty check. If STDOUT is not a tty, don't do color.
|
||||
#
|
||||
# 1.1.0 Added the "nocolor" option to turn off the color if the terminal type
|
||||
# ($TERM) is listed.
|
||||
#
|
||||
# 1.0.0 Initial Version
|
||||
|
||||
use strict;
|
||||
|
||||
use Term::ANSIColor;
|
||||
use IPC::Open3;
|
||||
use Cwd 'abs_path';
|
||||
|
||||
my(%nocolor, %colors, %compilerPaths);
|
||||
my($unfinishedQuote, $previousColor);
|
||||
|
||||
sub initDefaults
|
||||
{
|
||||
$nocolor{"dumb"} = "true";
|
||||
|
||||
$colors{"srcColor"} = color("cyan");
|
||||
$colors{"introColor"} = color("blue");
|
||||
|
||||
$colors{"warningFileNameColor"} = color("yellow");
|
||||
$colors{"warningNumberColor"} = color("yellow");
|
||||
$colors{"warningMessageColor"} = color("yellow");
|
||||
|
||||
$colors{"errorFileNameColor"} = color("bold red");
|
||||
$colors{"errorNumberColor"} = color("bold red");
|
||||
$colors{"errorMessageColor"} = color("bold red");
|
||||
}
|
||||
|
||||
sub loadPreferences
|
||||
{
|
||||
# Usage: loadPreferences("filename");
|
||||
|
||||
my($filename) = @_;
|
||||
|
||||
open(PREFS, "<$filename") || return;
|
||||
|
||||
while(<PREFS>)
|
||||
{
|
||||
next if (m/^\#.*/); # It's a comment.
|
||||
next if (!m/(.*):\s*(.*)/); # It's not of the form "foo: bar".
|
||||
|
||||
my $option = $1;
|
||||
my $value = $2;
|
||||
|
||||
if ($option eq "nocolor")
|
||||
{
|
||||
# The nocolor option lists terminal types, separated by
|
||||
# spaces, not to do color on.
|
||||
foreach my $term (split(' ', $value))
|
||||
{
|
||||
$nocolor{$term} = 1;
|
||||
}
|
||||
}
|
||||
elsif (defined $colors{$option})
|
||||
{
|
||||
$colors{$option} = color($value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$compilerPaths{$option} = $value;
|
||||
}
|
||||
}
|
||||
close(PREFS);
|
||||
}
|
||||
|
||||
sub srcscan
|
||||
{
|
||||
# Usage: srcscan($text, $normalColor)
|
||||
# $text -- the text to colorize
|
||||
# $normalColor -- The escape sequence to use for non-source text.
|
||||
|
||||
# Looks for text between ` and ', and colors it srcColor.
|
||||
|
||||
my($line, $normalColor) = @_;
|
||||
|
||||
if (defined $normalColor)
|
||||
{
|
||||
$previousColor = $normalColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
$normalColor = $previousColor;
|
||||
}
|
||||
|
||||
my($srcon) = color("reset") . $colors{"srcColor"};
|
||||
my($srcoff) = color("reset") . $normalColor;
|
||||
|
||||
$line = ($unfinishedQuote? $srcon : $normalColor) . $line;
|
||||
|
||||
# These substitutions replaces `foo' with `AfooB' where A is the escape
|
||||
# sequence that turns on the the desired source color, and B is the
|
||||
# escape sequence that returns to $normalColor.
|
||||
|
||||
# Handle multi-line quotes.
|
||||
if ($unfinishedQuote) {
|
||||
if ($line =~ s/^([^\`]*?)\'/$1$srcoff\'/)
|
||||
{
|
||||
$unfinishedQuote = 0;
|
||||
}
|
||||
}
|
||||
if ($line =~ s/\`([^\']*?)$/\`$srcon$1/)
|
||||
{
|
||||
$unfinishedQuote = 1;
|
||||
}
|
||||
|
||||
# Single line quoting.
|
||||
$line =~ s/\`(.*?)\'/\`$srcon$1$srcoff\'/g;
|
||||
|
||||
print($line, color("reset"));
|
||||
}
|
||||
|
||||
#
|
||||
# Main program
|
||||
#
|
||||
|
||||
# Set up default values for colors and compilers.
|
||||
initDefaults();
|
||||
|
||||
# Read the configuration file, if there is one.
|
||||
my $configFile = $ENV{"HOME"} . "/.colorgccrc";
|
||||
if (-f $configFile)
|
||||
{
|
||||
loadPreferences($configFile);
|
||||
}
|
||||
elsif (-f '/etc/colorgcc/colorgccrc')
|
||||
{
|
||||
loadPreferences('/etc/colorgcc/colorgccrc');
|
||||
}
|
||||
|
||||
# Set our default output color. This presumes that any unrecognized output
|
||||
# is an error.
|
||||
$previousColor = $colors{"errorMessageColor"};
|
||||
|
||||
# Figure out which compiler to invoke based on our program name.
|
||||
$0 =~ m%.*/(.*)$%;
|
||||
my $progName = $1 || $0;
|
||||
my $compiler_pid;
|
||||
|
||||
# If called as "colorgcc", just filter STDIN to STDOUT.
|
||||
if ($progName eq 'colorgcc')
|
||||
{
|
||||
open(GCCOUT, "<&STDIN");
|
||||
}
|
||||
else
|
||||
{
|
||||
# See if the user asked for a specific compiler.
|
||||
my $compiler;
|
||||
if (!defined($compiler = $compilerPaths{$progName}))
|
||||
{
|
||||
# Find our wrapper dir on the PATH and tweak the PATH to remove
|
||||
# everything up-to and including our wrapper dir.
|
||||
if ($0 =~ m#(.*)/#)
|
||||
{
|
||||
# We were called with an explicit path, so trim that off the PATH.
|
||||
my $find = $1;
|
||||
$find = abs_path($1) unless $find =~ m#^/#;
|
||||
$ENV{'PATH'} =~ s#.*(^|:)\Q$find\E(:|$)##;
|
||||
}
|
||||
else
|
||||
{
|
||||
my(@dirs) = split(/:/, $ENV{'PATH'});
|
||||
while (defined($_ = shift @dirs))
|
||||
{
|
||||
if (-x "$_/$progName")
|
||||
{
|
||||
$ENV{'PATH'} = join(':', @dirs);
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
$compiler = $progName;
|
||||
}
|
||||
|
||||
# Get the terminal type.
|
||||
my $terminal = $ENV{"TERM"} || "dumb";
|
||||
|
||||
# If it's in the list of terminal types not to color, or if
|
||||
# we're writing to something that's not a tty, don't do color.
|
||||
if (! -t STDOUT || $nocolor{$terminal})
|
||||
{
|
||||
exec $compiler, @ARGV
|
||||
or die("Couldn't exec");
|
||||
}
|
||||
|
||||
# Keep the pid of the compiler process so we can get its return
|
||||
# code and use that as our return code.
|
||||
$compiler_pid = open3('<&STDIN', \*GCCOUT, \*GCCOUT, $compiler, @ARGV);
|
||||
}
|
||||
|
||||
# Colorize the output from the compiler.
|
||||
while(<GCCOUT>)
|
||||
{
|
||||
if (m#^(.+?\.[^:/ ]+):([0-9]+):(.*)$#) # filename:lineno:message
|
||||
{
|
||||
my $field1 = $1 || "";
|
||||
my $field2 = $2 || "";
|
||||
my $field3 = $3 || "";
|
||||
|
||||
if ($field3 =~ m/\s+warning:.*/)
|
||||
{
|
||||
# Warning
|
||||
print($colors{"warningFileNameColor"}, "$field1:", color("reset"));
|
||||
print($colors{"warningNumberColor"}, "$field2:", color("reset"));
|
||||
srcscan($field3, $colors{"warningMessageColor"});
|
||||
}
|
||||
else
|
||||
{
|
||||
# Error
|
||||
print($colors{"errorFileNameColor"}, "$field1:", color("reset"));
|
||||
print($colors{"errorNumberColor"}, "$field2:", color("reset"));
|
||||
srcscan($field3, $colors{"errorMessageColor"});
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
elsif (m/^:.+`.*'$/) # filename:message:
|
||||
{
|
||||
srcscan($_, $colors{"warningMessageColor"});
|
||||
}
|
||||
elsif (m/^(.*?):(.+):$/) # filename:message:
|
||||
{
|
||||
# No line number, treat as an "introductory" line of text.
|
||||
srcscan($_, $colors{"introColor"});
|
||||
}
|
||||
else # Anything else.
|
||||
{
|
||||
srcscan($_, undef);
|
||||
}
|
||||
}
|
||||
|
||||
if ($compiler_pid)
|
||||
{
|
||||
# Get the return code of the compiler and exit with that.
|
||||
waitpid($compiler_pid, 0);
|
||||
exit ($? >> 8);
|
||||
}
|
Loading…
Reference in New Issue