Skip to content

Instantly share code, notes, and snippets.

@blondie7575 blondie7575/eetool.c
Created Aug 29, 2015

Embed
What would you like to do?
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdio.h>
#include <LUFA/Drivers/USB/USB.h>
#include "Descriptors.h"
#include "Macros.h"
#define BUFF_SIZE 512
#define LEDPIN 6
#define PREFIXBYTE 0x42
#define ROMSIZE 32768
void SetupHardware(void);
void FatalError(void);
void ClearCommand(void);
void Echo(const char* string);
void WriteBlock(void);
void ReadBlock(uint16_t startAddr, uint16_t length, bool maskROM);
void SetAddressMSB(uint8_t addr, bool maskROM);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
void EVENT_USB_Device_ConfigurationChanged(void);
void EVENT_USB_Device_ControlRequest(void);
// LUFA CDC Class driver interface configuration and state information.
USB_ClassInfo_CDC_Device_t EETool_CDC_Interface =
{
.Config =
{
.ControlInterfaceNumber = INTERFACE_ID_CDC_CCI,
.DataINEndpoint =
{
.Address = CDC_TX_EPADDR,
.Size = CDC_TXRX_EPSIZE,
.Banks = 1,
},
.DataOUTEndpoint =
{
.Address = CDC_RX_EPADDR,
.Size = CDC_TXRX_EPSIZE,
.Banks = 1,
},
.NotificationEndpoint =
{
.Address = CDC_NOTIFICATION_EPADDR,
.Size = CDC_NOTIFICATION_EPSIZE,
.Banks = 1,
},
},
};
typedef enum
{
CMD_NONE,
CMD_PING,
CMD_STARTRW,
CMD_READBLOCK,
CMD_WRITEBLOCK
} Command;
Command gCurrentCommand = CMD_NONE;
uint8_t gCommBuffer[BUFF_SIZE] = "";
uint16_t gCurrentAddress = 0;
int main(void)
{
SetupHardware();
GlobalInterruptEnable();
for (;;)
{
// Check for host data
uint16_t byteCount = CDC_Device_BytesReceived(&EETool_CDC_Interface);
byteCount = MIN(byteCount,BUFF_SIZE-1);
if (byteCount>BUFF_SIZE)
{
FatalError();
}
if (byteCount>0)
{
// Read all data from host
int i;
for (i=0; i<byteCount; i++)
{
int16_t value = CDC_Device_ReceiveByte(&EETool_CDC_Interface);
if (value>=0)
{
gCommBuffer[i] = (uint8_t)value;
}
}
// Check for new command
if (gCurrentCommand==CMD_NONE && gCommBuffer[0]==PREFIXBYTE)
{
gCurrentCommand = gCommBuffer[1];
// New command
switch (gCurrentCommand)
{
case CMD_PING:
{
Echo("PONG");
ClearCommand();
break;
}
case CMD_STARTRW:
{
gCurrentAddress = 0;
PULSEC(LEDPIN);
break;
}
case CMD_READBLOCK:
{
ReadBlock(gCurrentAddress,BUFF_SIZE,false);
gCurrentAddress += BUFF_SIZE;
break;
}
default:
FatalError();
break;
}
ClearCommand();
}
}
CDC_Device_USBTask(&EETool_CDC_Interface);
USB_USBTask();
}
}
void SetupHardware(void)
{
// Disable watchdog if enabled by bootloader/fuses
MCUSR &= ~(1 << WDRF);
wdt_disable();
// Disable clock division
clock_prescale_set(clock_div_1);
// Configure IO pins
// Address bus, LSB
DDRB = QDDRB(0) | QDDRB(1) | QDDRB(2) | QDDRB(3) | QDDRB(4) | QDDRB(5) | QDDRB(6) | QDDRB(7);
// Address bus, MSB
DDRF = QDDRF(0) | QDDRF(1) | QDDRF(4) | QDDRF(5) | QDDRF(6) | QDDRF(7);
DDRC = QDDRC(6) | QDDRC(7); // Also LED output
// Control bits
DDRE = QDDRE(2) | QDDRE(6); // Output enable , Write Enable / Mask ROM high bit
// Initialize control signals
SETE_HI(6);
SETE_HI(2);
SETC_LO(LEDPIN);
USB_Init();
}
void FatalError(void)
{
for (;;)
{
SETC_LO(LEDPIN);
_delay_ms(50);
SETC_HI(LEDPIN);
_delay_ms(50);
}
}
void ClearCommand(void)
{
gCommBuffer[0] = 0;
gCurrentCommand = CMD_NONE;
}
void Echo(const char* string)
{
PULSEC(LEDPIN);
CDC_Device_SendString(&EETool_CDC_Interface, string);
}
void SetAddressMSB(uint8_t addr, bool maskROM)
{
// Drives the high address lines to the specified value. These lines
// are all mixed up to get around the holes in the AVR's IO space
if (addr & 0x1)
{
SETF_HI(0);
}
else
{
SETF_LO(0);
}
addr>>=1;
if (addr & 0x1)
{
SETF_HI(1);
}
else
{
SETF_LO(1);
}
addr>>=1;
if (addr & 0x1)
{
SETF_HI(4);
}
else
{
SETF_LO(4);
}
addr>>=1;
if (addr & 0x1)
{
SETF_HI(5);
}
else
{
SETF_LO(5);
}
addr>>=1;
if (addr & 0x1)
{
SETF_HI(6);
}
else
{
SETF_LO(6);
}
addr>>=1;
if (addr & 0x1)
{
SETF_HI(7);
}
else
{
SETF_LO(7);
}
addr>>=1;
if (maskROM)
{
SETC_HI(7); // For Mask ROM, this provides extra Vcc
if (addr & 0x1)
{
SETE_HI(6);
}
else
{
SETE_LO(6);
}
}
else
{
if (addr & 0x1)
{
SETC_HI(7);
}
else
{
SETC_LO(7);
}
}
}
void ReadBlock(uint16_t startAddr, uint16_t length, bool maskROM)
{
if (startAddr >= ROMSIZE)
{
FatalError();
}
_delay_ms(10); // Give the host a moment to set up before we flood them with data
DDRD = 0; // Data bus for input
SETE_HI(2); // Initialize Output Enable
if (!maskROM)
{
SETE_HI(6); // Write Enable to disable
}
for (uint16_t i=startAddr; i<startAddr+length; i++)
{
// Drive address lines
PORTB = (uint8_t)(i & 0xff); // LSB
SetAddressMSB((uint8_t)(i>>8),maskROM);
// Show falling edge to Output Enable
SETE_LO(2);
_delay_us(1);
// Read the data byte
uint8_t data = PIND;
SETE_HI(2);
uint16_t index = i-startAddr;
if (index>=BUFF_SIZE)
{
FatalError();
}
gCommBuffer[index] = data;
}
// Send data to host
CDC_Device_SendData(&EETool_CDC_Interface, gCommBuffer, length);
_delay_ms(10);
PULSEC(LEDPIN);
}
void WriteBlock()
{
// Data bus for output
DDRD = QDDRD(0) | QDDRD(1) | QDDRD(2) | QDDRD(3) | QDDRD(4) | QDDRD(5) | QDDRD(6) | QDDRD(7);
}
// USB Event Handlers
void EVENT_USB_Device_Connect(void)
{
SETC_HI(LEDPIN);
}
void EVENT_USB_Device_Disconnect(void)
{
SETC_LO(LEDPIN);
}
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
ConfigSuccess &= CDC_Device_ConfigureEndpoints(&EETool_CDC_Interface);
}
void EVENT_USB_Device_ControlRequest(void)
{
CDC_Device_ProcessControlRequest(&EETool_CDC_Interface);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.