Old computer enthusiasm and chemistry wizardry have come up with a recipe for undoing the supposedly permanent effects of UV and fire retardants!
I'm definitely going to try this out, as soon as I can get hold of the requisite chemicals...
Sorted by Squirrels.




10@=0
20!#208=!#208+3
30V=#B800
40W=#FFF4
50T=#80
60DIM LL(13),C(6)
70F.N=0TO13;LL(N)=#FFFF;N.N
80F.N=1TO2; DIM P(-1)
90P."PASS "N',$21
100[
110\ main
120:LL0 LDA @#0
130STA C+1; STA C+2; STA C+3; STA C+4
140LDA @#95; STA C+0
150JSR LL3
160LDA @#40+#0; JSR LL7
170LDA @CH"1"; SBC @0; JMP W
180\ select card
190:LL1 LDA @0; STA V; RTS
200\ deselect card
210:LL2 LDA @#20; STA V; RTS
220\ init hw and go spi
230:LL3 LDA @0; STA V+#C
240LDA @#FE; STA V+2
250LDA @#20; STA V
260LDY @10
270:LL4 LDA @#FF; JSR LL5; DEY; BNE LL4
280RTS
290\ xferbyte
300:LL5 STX T+0; STY T+1; LDY @8
310:LL6 PHA; AND @#80; STA V
320ORA @#40; STA V
330LDX V; AND @#BF; STA V
340TXA; ROR A
350PLA; ROL A
360DEY; BNE LL6
370PHA; JSR #F7FA; PLA
380LDY T+1; LDX T+0;
390RTS
400\ command
410:LL7 STA C+5; LDY @5
420:LL8 LDA C,Y; JSR LL5; DEY; BPL LL8
430:LL9 LDA @#FF; JSR LL5; AND @#FF; CLC; BPL LL10
440DEY; BNE LL9;
450SEC
460:LL10 RTS
470]
480P.$6
490NE.N
500END




I've been inspired by someone or other's homebuilt spinner. I probably saw it on Make or Hack-a-day, I forget. If you aren't familiar with the aforementioned input device it's like, well you know, like an arcade game control that could be found on such classics as Tempest, Arkanoid, Cameltry and many many more. You spin it. Hence the name. /*
/ Microfat.
/
/ Developed by Charlie Robson in 2008.
/
/ This is the bare minimum* functionality required to read and write data
/ to a FAT formatted device. In this case, an MMC card.
/
/ Rather than build a fully-featured FAT implimentation this will allow
/ the user to locate sectors associated with a file on the device, and
/ read and write to them in a brute force manner. No error checking, no
/ long filenames, not even any support for fragmented files :) This is
/ raw access, we only deal with existing files.
/
/ What you do get is a very lightweight module for extremely limited
/ environments. Arduino has 2k of SRAM. Holding the sector of FAT data
/ needed to traverse a fragged file would instantly gobble up 1/4
/ of that. Enough said. Another benefit to not using the FAT is that
/ there's no need to worry about whether a device is FAT12 or 16.
/
/ To use:
/ Format a card.
/ Make a file big enough to hold all the data you expect to write.
/ Copy to the card.
/
/ With the MMC module started up, call initialise. This will cache some
/ relevant information about the card such as the sector location of the
/ root directory and data area.
/
/ Call locateFileStart, passing the name of the file which is providing
/ the backing store for your transfers, and assuming the file is found
/ in the directory you'll receive its start sector and file size.
/
/ Now feel free to read and write data to and from the sectors allocated
/ to the file. Code carefully though - stray writes can twat your card!
/
/ Enjoy :)
/
/ *Massive understatement!
*/
#ifndef __MICROFAT_H__
#define __MICROFAT_H__
// some data structures we'll be encountering on our travels.
typedef struct
{
byte bootable;
byte chsAddrOfFirstSector[3];
byte partitionType;
byte chsAddrOfLastSector[3];
uint32_t lbaAddrOfFirstSector;
uint32_t partitionLengthSectors;
}
partition_record;
typedef struct
{
byte jump[3];
char oemName[8];
uint16_t bytesPerSector;
byte sectorsPerCluster;
uint16_t reservedSectors;
byte fatCopies;
uint16_t rootDirectoryEntries;
uint16_t totalFilesystemSectors;
byte mediaDescriptor;
uint16_t sectorsPerFAT;
uint16_t sectorsPerTrack;
uint16_t headCount;
uint32_t hiddenSectors;
uint32_t totalFilesystemSectors2;
byte logicalDriveNum;
byte reserved;
byte extendedSignature;
uint32_t partitionSerialNum;
char volumeLabel[11];
char fsType[8];
byte bootstrapCode[447];
byte signature[2];
}
boot_sector;
typedef struct
{
char filespec[11];
byte attributes;
byte reserved[10];
uint16_t time;
uint16_t date;
uint16_t startCluster;
uint32_t fileSize;
}
directory_entry;
namespace microfat
{
// Cache some relevant info about the card.
//
bool initialise(byte* buffer);
// Get start sector, file size for given filename. Returns false if the file
// is not found in the directory.
//
bool locateFileStart(const char* filename, unsigned long& sector, unsigned long& size);
};
#endif // __MICROFAT_H__
#include <wprogram.h>
#include "microfat.h"
#include "mmc.h"
// Data which remains constant over one session. Re-initialise if
// the card is changed.
//
static struct
{
uint16_t sectorsPerCluster;
uint32_t rootDirSect, cluster2;
byte* buffer;
}
vars;
bool microfat::initialise(byte* buffer)
{
vars.buffer = buffer;
if (RES_OK != mmc::readSectors(vars.buffer, 0, 1))
{
return false;
}
partition_record* p = (partition_record*)&vars.buffer[0x1be];
long bootSector = p->lbaAddrOfFirstSector;
if (RES_OK != mmc::readSectors(vars.buffer, bootSector, 1))
{
return false;
}
boot_sector* b = (boot_sector*)vars.buffer;
if (BYTESPERSECTOR != b->bytesPerSector)
{
return false;
}
vars.sectorsPerCluster = b->sectorsPerCluster;
vars.rootDirSect = bootSector + b->reservedSectors + (b->fatCopies * b->sectorsPerFAT);
long dirBytes = b->rootDirectoryEntries * 32;
long dirSects = dirBytes / BYTESPERSECTOR;
if (dirBytes % BYTESPERSECTOR != 0)
{
++dirSects;
}
vars.cluster2 = vars.rootDirSect + dirSects;
return true;
}
// Get start sector for given filename.
//
// Returns false if the specified file wasn't found in the directory.
// Short filenames only. Be aware that the directory fills up with 'deleted'
// filenames. Rather than deleting too many files try a quick reformat.
//
bool microfat::locateFileStart(const char* filename, uint32_t& sector, uint32_t& size)
{
if (RES_OK == mmc::readSectors(vars.buffer, vars.rootDirSect, 1))
{
// The filenames are stored in [8][3] format. No dot, all upper case.
// Names shorter than 8 chars are padded with spaces.
//
// Cook the supplied name. fred.txt -> FRED----TXT
//
char cookedName[11];
for(int i = 0; i < 12; ++i)
{
cookedName[i] = 0x20;
}
for (int i = 0, j = 0; i < 12 && filename[i]; ++i)
{
if (filename[i] != '.')
{
// Force char to uppercase. Cheesy I know :)
//
cookedName[j] = filename[i] >= 96 ? filename[i] - 32 : filename[i];
++j;
}
else
{
// Continue cooking chars at the extension position
//
j = 8;
}
}
for (int i = 0; i < BYTESPERSECTOR; i += 32)
{
directory_entry* de = (directory_entry*)&vars.buffer[i];
// Don't match with deleted or system/volname/subdir/hidden files
//
if (de->filespec[0] != 0xe5 && (de->attributes & 0x1e) == 0 && memcmp(cookedName, de->filespec, 11) == 0)
{
sector = vars.cluster2 + ((de->startCluster-2) * vars.sectorsPerCluster);
size = de->fileSize;
return true;
}
}
}
return false;
}

/*
* Support code for ACE - the arduino cassette engine
*
* Example code to write a wav file which can be played to
* a microcontroller running the ACE software.
*
* Should be fairly portable unlike the original example.
*
* Enjoy.
*
*/
#include <iostream>
#include <fstream>
typedef unsigned char uint8_t;
// adjust these to control endiannesses.
//
static const int ENDIAN0 = 0;
static const int ENDIAN1 = 1;
static const int ENDIAN2 = 2;
static const int ENDIAN3 = 3;
static const int ENDIAN0_S = 0;
static const int ENDIAN1_S = 1;
// desired wave structure - AHEM THESE ARE READ-ONLY
// - THEY CAN'T BE CHANGED WITHOUT FUTZING THE CODE. SORRY.
//
static const int CHANNELS = 2;
static const int SAMPLERATE = 44100;
static const int BITSPERSAMPLE = 16;
// this is as loud as we can get. not quite 11,
// but approaching it.
//
static const double maxLevel = (double)SHRT_MAX * 1.0;
static const short maxLevelS = (short)maxLevel;
static const double minLevel = (double)SHRT_MIN * 1.0;
static const short minLevelS = (short)minLevel;
// number of samples per cycle. 60 samples = 1 low or 2 high cycles.
//
static const int f1 = 60;
static const int f1cyc = 1;
static const int f2 = f1 / 2;
static const int f2cyc = f1cyc * 2;
// useful values, maybe
//
static const int usPerCycle = (int)(((double)f1 / 44100) * 1000000.0);
static const int usPerHalfCycle = (int)(((double)f1 / 44100) * 500000.0);
static const int usPerQuarterCycle = (int)(((double)f1 / 44100) * 250000.0);
static const int usPerEighthCycle = (int)(((double)f1 / 44100) * 125000.0);
static const int baudrate = (1000000 / usPerCycle);
// 8 + stop + start;
//
static const int bitsPerFrame = 10;
static const int samplesPerBit = f1 * f1cyc;
static const int samplesPerFrame = bitsPerFrame * samplesPerBit;
static const int LOW_BIT = 0;
static const int HIGH_BIT = !LOW_BIT;
static const int LEADIN_BIT = LOW_BIT;
static const int START_BIT = !LEADIN_BIT;
static const int STOP_BIT = !START_BIT;
// NASTY HACK FOR WRITING WAVS. PLEASE LOOK AWAY NOW.
void CreateWaveFile(std::ostream& output)
{
char chars[4];
output << "RIFF";
*(int*)chars = 16;
output << chars[ENDIAN0] << chars[ENDIAN1] << chars[ENDIAN2] << chars[ENDIAN3];
output << "WAVE";
output << "fmt ";
*(int*)chars = 16;
output << chars[ENDIAN0] << chars[ENDIAN1] << chars[ENDIAN2] << chars[ENDIAN3];
*(short*)chars = 1;
output << chars[ENDIAN0_S] << chars[ENDIAN1_S];
*(short*)chars = CHANNELS;
output << chars[ENDIAN0_S] << chars[ENDIAN1_S];
*(int*)chars = SAMPLERATE;
output << chars[ENDIAN0] << chars[ENDIAN1] << chars[ENDIAN2] << chars[ENDIAN3];
*(int*)chars = (int)(SAMPLERATE*(BITSPERSAMPLE/8*CHANNELS));
output << chars[ENDIAN0] << chars[ENDIAN1] << chars[ENDIAN2] << chars[ENDIAN3];
*(short*)chars = (short)(BITSPERSAMPLE/8*CHANNELS);
output << chars[ENDIAN0_S] << chars[ENDIAN1_S];
*(short*)chars = (short)BITSPERSAMPLE;
output << chars[ENDIAN0_S] << chars[ENDIAN1_S];
output << "data";
*(int*)chars = 0;
output << chars[ENDIAN0] << chars[ENDIAN1] << chars[ENDIAN2] << chars[ENDIAN3];
}
void FinaliseWaveFile(std::ostream& output, size_t bytesWrit)
{
char chars[4];
output.seekp(40);
*(int*)chars = (int)bytesWrit;
output << chars[ENDIAN0] << chars[ENDIAN1] << chars[ENDIAN2] << chars[ENDIAN3];
output.seekp(4);
*(int*)chars = (int)(bytesWrit + 36);
output << chars[ENDIAN0] << chars[ENDIAN1] << chars[ENDIAN2] << chars[ENDIAN3];
}
// OK IT'S SAFE TO LOOK AGAIN
// here we represent:
//
// 0 bit as 1 cycle of low frequency,
// 1 bit as 2 cycles of high frequency
//
// where the high frequency is double that of the low.
//
void OutputBit(std::ostream& output, int bit, size_t& written,
short maxval = maxLevelS, short minval = minLevelS)
{
// default to low
//
int cycles = f1cyc;
int samplesPerCycle = f1;
if (bit != 0)
{
cycles = f2cyc;
samplesPerCycle = f2;
}
// generate square pulse, start with rising edge
//
for (int i = 0; i < cycles; ++i)
{
for (int j = 0; j < samplesPerCycle / 2; ++j)
{
// high [1] period
//
output << uint8_t(maxval & 0xff);
output << uint8_t(maxval >> 8);
output << uint8_t(maxval & 0xff);
output << uint8_t(maxval >> 8);
written += 4;
}
for (int j = 0; j < samplesPerCycle / 2; ++j)
{
// low [0] period
//
output << uint8_t(minval & 0xff);
output << uint8_t(minval >> 8);
output << uint8_t(minval & 0xff);
output << uint8_t(minval >> 8);
written += 4;
}
}
}
// outputs a start bit, 8 data bits and a stop bit
//
void OutputByte(std::ostream& output, uint8_t value, size_t& written)
{
OutputBit(output, START_BIT, written);
for (int i = 0; i < 8; ++i)
{
OutputBit(output, (value & 0x80) ? HIGH_BIT : LOW_BIT, written);
value <<= 1;
}
OutputBit(output, STOP_BIT, written);
}
// outputs a lead train of bits, terminated with a start bit.
//
void OutputLeader(std::ostream& output, int milliseconds, size_t& written)
{
int microseconds = (milliseconds * 1000) - usPerCycle;;
// this is a bit of a decoration -
// ramp up the volume during the 1st half of the leader. this might
// prevent some unexpected eardrum-rupture events.. and yes, i know
// that volume should be ramped non-linearly :) this will do for
// the time being.
//
double vol = 0, ramp = 1.0 / (microseconds/(usPerCycle*2));
while (microseconds >= 0)
{
OutputBit(output, LEADIN_BIT, written, (short)(vol * maxLevel), (short)(vol * minLevel));
vol += ramp;
vol = __min(vol, 1.0);
microseconds -= usPerCycle;
}
OutputBit(output, START_BIT, written);
}
void main (int argc, char **argv)
{
if (argc < 3)
{
std::cout << "Usage: makewav [input file] [output file]" << std::endl;
exit(1);
}
std::ifstream inner(argv[1], std::ios_base::binary);
if (!inner.is_open())
{
std::cout << "Could not open input file." << std::endl;
exit(1);
}
std::ofstream outer(argv[2], std::ios_base::binary);
if (!outer.is_open())
{
std::cout << "Could not open output file." << std::endl;
exit(1);
}
// write wav header
//
CreateWaveFile(outer);
// determine input file size
//
inner.seekg(0, std::ios_base::end);
size_t size = (size_t)inner.tellg();
inner.seekg(0);
size_t pc = 0;
size_t written = 0;
// file is structured:
// some seconds of leader
// size msb
// size lsb
// {
// data[512]
// some milliseconds of leader
// }
OutputLeader(outer, 2000, written);
OutputByte(outer, uint8_t(size >> 8), written);
OutputByte(outer, uint8_t(size & 0xff), written);
while (pc != size)
{
// dummy data - replace this with either read from buffer indexed by [pc]
// or a byte get from the file to be encoded
//
OutputByte(outer, inner.get(), written);
++pc;
if (pc % 512 == 0 && pc != size)
{
OutputLeader(outer, 50, written);
}
}
FinaliseWaveFile(outer, written);
outer.close();
}
I've been laid up with a succession of minor bugs of the viral kind and subsequently there's been no movement on the hardware front. I think it's time to post something though and with that in mind please be upstanding for the one - the only - ACE! /*
/ 'Arduino Cassette Engine'.
/
/ Developed by Charlie Robson in 2008.
/
/ This is half of a solution for getting data into an arduino. The other
/ half being code to generate frequency shift keyed (FSK) data in the form
/ of WAV files which should be widely playable. These can be recorded or
/ otherwise electronically distributed. Why do it this way? 1. Because it's
/ funny. 2. Having given an updatable arduino-powered 'toy' to someone, I
/ can't expect them to re-program the device by traditional means in order
/ to update it. Everyone has a means of playing a sound!
/
/ On with the show.
/
/ The data is encoded like so:
/
/ Lead-in
/ High byte of data length
/ Low byte of data length
/ {
/ Data[0 < size <= 512]
/ (Lead-in)
/ }
/
/ Lead-in is a train of bits terminated with a start bit. This means the lead-in
/ bit needs to be the logical complement of the start bit.
/
/ Every byte is represented by 10 bits - a start bit, 8 data bits, and a stop
/ bit. The start and stop bits are complementary.
/
/ Data arrives in 512 byte blocks. Each block except the last is followed by a
/ short period, about 25 milliseconds, of lead-in. This is to allow processing time
/ on each block as it arrives.
/
/ Decoding a data bit is done something like so:
/
/ Await a rising edge then take 2 samples at a period which will allow us
/ to distinguish a 0 or 1 bit. Sampling 2 identical values yields a 0 bit.
/ Delay so the next bit read will occur when the signal is in a low period.
/
/ Following is a picture of a '0' bit, or low frequency cycle, followed by
/ a '1' bit or high frequency cycle, with some important times noted.
/
/ The X shows a rough expected time at which we start the bit reading.
/ The 0 shows relative time zero, when we detect the rising edge.
/ The + signs show the times at which we sample.
/ The * shows the earliest time at which we can await a new bit. IOW, X.
/
/ __`_____`__ __
/ | ` ` | |
/ | ` ` | |
/ | ` ` | ` |
/ ` | ` ` | ` |
/ __`_| ` ` | ____`_____|
/ ` ` ` ` `
/ X 0 + + *
/ ` `__`__ ` _____`
/ ` | ` | ` | |
/ ` | ` | ` | |
/ | | | |
/ | | | | |
/ ____| |_____| |_____|
/ `
/ `
/ |-----------------------| = usPerCycle = 1360uS
/ |-----------| = usPerHalfCycle = 680uS
/ |-----| = usPerQuarterCycle = 340uS
/ |--| = usPerEighthCycle = 170uS
/
/
/ It's assumed that the audio signal is connected to PORTB-0 which is
/ digital pin 8. If you'd like to change that, then replace occurrences
/ of...
/
/ PINB & 1
/
/ ... with the direct bit-access for your implementation. I do it this
/ way because it's slightly faster than digitalRead()ing. If you do change
/ the port you'll also need to change the logic in readBit as this relies
/ on the fact that we work with bit 0.
/
*/


There wasn't any software that would drive the parallel port breakout cable that I built. (Yes, I know it's ironic given my previous statement about how I wasn't prepared to solder up another DB25!!)// XA1 XA0 Action when XTAL1 is Pulsed
// --- --- ---------------------------
// 0 0 Load Flash or EEPROM Address (High or low address byte determined by BS1)
// 0 1 Load Data (High or Low data byte for Flash determined by BS1)
// 1 0 Load Command
// 1 1 No Action, Idle
//
const byte XA_LOAD_ADDR = B00;
const byte XA_LOAD_DATA = B01;
const byte XA_LOAD_CMND = B10;
const byte XA_NOP = B11;
const byte CMD_ERASE = B10000000;
const byte CMD_WRITE_FUSE = B01000000;
const byte CMD_READ_SIG = B00001000;
const byte CMD_READ_FUSE = B00000100;
#define DLY delayMicroseconds(100)
inline void SETB(byte x)
{
PORTB |= _BV(x);
DLY;
}
inline void SETD(byte x)
{
PORTD |= _BV(x);
DLY;
}
inline void CLRB(byte x)
{
PORTB &= ~_BV(x);
DLY;
}
inline void CLRD(byte x)
{
PORTD &= ~_BV(x);
DLY;
}
// PORTB
#define PIN_BS1 0
#define PIN_XA0 1
#define PIN_XA1 2
#define PIN_BS2 3
#define PIN_PAGEL 4
#define PIN_POWERTOCHIP 5
#define SET_BS1 SETB(PIN_BS1)
#define CLR_BS1 CLRB(PIN_BS1)
void SET_XA(byte xtal_action)
{
PORTB &= ~(_BV(PIN_XA1)|_BV(PIN_XA0));
PORTB |= xtal_action << PIN_XA0;
DLY;
}
void CLR_XA()
{
PORTB &= ~(_BV(PIN_XA1)|_BV(PIN_XA0));
DLY;
}
#define SET_BS2 SETB(PIN_BS2)
#define CLR_BS2 CLRB(PIN_BS2)
#define SET_PAGEL SETB(PIN_PAGEL)
#define CLR_PAGEL CLRB(PIN_PAGEL)
#define SET_POWERTOCHIP SETB(PIN_POWERTOCHIP)
#define CLR_POWERTOCHIP CLRB(PIN_POWERTOCHIP)
// PORTD
#define PIN_XTAL1 2
#define PIN_RDYNOTBSY 3
#define PIN_OE 4
#define PIN_WR 5
// <- PORTD3 rdy/bsy
//
void AWAIT_READY()
{
while ((PIND & _BV(PIN_RDYNOTBSY)) == 1);
long time = millis();
while ((PIND & _BV(PIN_RDYNOTBSY)) == 0);
Serial.println(millis()-time,DEC);
}
#define SET_OE SETD(PIN_OE)
#define CLR_OE CLRD(PIN_OE)
#define SET_WR SETD(PIN_WR)
#define CLR_WR CLRD(PIN_WR)
void PULSE_WR(bool wait = true);
void PULSE_WR(bool wait)
{
PORTD &= ~_BV(PIN_WR);
delayMicroseconds(100);
PORTD |= _BV(PIN_WR);
if (wait)
{
AWAIT_READY();
}
}
#define SET_XTAL1 SETD(PIN_XTAL1)
#define CLR_XTAL1 CLRD(PIN_XTAL1)
void PULSE_XTAL(bool wait = true);
void PULSE_XTAL(bool wait)
{
PORTD |= _BV(PIN_XTAL1);
delayMicroseconds(100);
PORTD &= ~_BV(PIN_XTAL1);
if (wait)
{
AWAIT_READY();
}
}
// <-> PORTD6...7 will be used as DATA6...7
// <-> PORTC0...5 will be used as DATA0...5
//
void SET_DATA_IN(void)
{
DDRC &= B11000000;
DDRD &= B00111111;
}
byte GET_DATA()
{
return (PORTC & B00111111) | (PORTD & B11000000);
}
void SET_DATA(byte data)
{
DDRC |= B00111111;
PORTC = (PORTC & B11000000) | (data & B00111111);
DDRD |= B11000000;
PORTD = (PORTD & B00111111) | (data & B11000000);
DLY;
}
//
//
//
void LOAD_COMMAND(byte command)
{
SET_XA(XA_LOAD_CMND);
SET_DATA(command);
PULSE_XTAL();
CLR_XA();
}
void LOAD_ADDRESS(byte address)
{
SET_XA(XA_LOAD_ADDR);
SET_DATA(address);
PULSE_XTAL();
CLR_XA();
}
void LOAD_DATA(byte data, bool low)
{
SET_XA(XA_LOAD_DATA);
if (!low)
{
SET_BS1;
}
SET_DATA(data);
PULSE_XTAL();
CLR_XA();
CLR_BS1;
}
byte GET_SIG(byte offset)
{
LOAD_COMMAND(CMD_READ_SIG);
LOAD_ADDRESS(offset);
SET_DATA_IN();
CLR_OE;
byte x = GET_DATA();
SET_OE;
}
inline void PROG_ENABLE(void)
{
SET_POWERTOCHIP;
delayMicroseconds(100);
}
inline void PROG_DISABLE(void)
{
CLR_POWERTOCHIP;
}
inline void PROG_ENABLE_PROPER(void)
{
SET_XTAL1;
CLR_XTAL1;
SET_XTAL1;
CLR_XTAL1;
SET_XTAL1;
CLR_XTAL1;
SET_POWERTOCHIP;
}
//
//
//
void setup(void)
{
Serial.begin(115200);
// PORTB 5...0 all outputs. Zero the ports before setting them as outputs
// to prevent spikes.
//
PORTB = 0;
DDRB |= B00111111;
// Not interested in DATA pins, they'll get set later as required
//
// PORTD0/1 are rx/tx: leave alone
// PORTD3 is input
// D6/7 are set on demand
// the rest are output
//
PORTD = 0;
DDRD = (DDRD & B11110111) | B00110100;
// bring the active low pins to their inactive state.
//
SET_OE;
SET_WR;
}
void loop(void)
{
Serial.println("Fuser 1.0 Ready.");
while(!Serial.available());
if (Serial.read() == 'p')
{
Serial.println("Sig: ");
PROG_ENABLE_PROPER();
Serial.println(GET_SIG(0),HEX);
Serial.println(GET_SIG(1),HEX);
Serial.println(GET_SIG(2),HEX);
}
else
{
Serial.println("Burn: ");
PROG_ENABLE();
delay(2);
Serial.println("Erase: ");
LOAD_COMMAND(CMD_ERASE);
PULSE_WR();
Serial.println("Lo fuse: ");
LOAD_COMMAND(CMD_WRITE_FUSE);
LOAD_DATA(0xE1, true);
PULSE_WR();
Serial.println("Hi fuse: ");
LOAD_COMMAND(CMD_WRITE_FUSE);
LOAD_DATA(0x99, false);
PULSE_WR();
}
PROG_DISABLE();
}
Target - atmega32
____ ____
| pb0 =| U |= pa0 | bs2
| 1 =| |=
/ | 2 =| |=
DATA | 3 =| |=
\ | 4 =| |=
| 5 =| |=
| 6 =| |=
| 7 =| |=
reset =| |= aref
vcc =| |= gnd
gnd =| |= avcc
=| |=
xtal1 | xtal1 =| |=
pd0 =| |=
rdy/~bsy | 1 =| |=
~oe | 2 =| |=
~wr | 3 =| |=
bs1 | 4 =| |=
xa0 | 5 =| |=
xa1 | 6 =|_________|= pd7 | pagel
Diecimila - pin assignment
ANA-IN5 |o| DATA5
4 |o| 4
3 |o| 3
2 |o| 2
1 |o| 1
0 |o| 0
D0 [rx] |o| -
1 [tx] |o| -
2 |o| xtal1
3 |o| rdy/~bsy
4 |o| ~oe
5 |o| ~wr
6 |o| DATA6
7 |o| DATA7
D8 |o| bs1
9 |o| xa0
10 |o| xa1
11 |o| bs2
12 |o| pagel
13 |o| juice
gnd |o| -
aref |o| -
/* CUT DUE TO ITS TEMPORARY NATURE - PLEASE SEE LATER POST */
