Skip to content

Instantly share code, notes, and snippets.

@doug65536
Created January 30, 2023 09:11
Show Gist options
  • Save doug65536/15024c21e09663fe5576879aa22b6cd9 to your computer and use it in GitHub Desktop.
Save doug65536/15024c21e09663fe5576879aa22b6cd9 to your computer and use it in GitHub Desktop.
#define PIN_RESET 22
#define PIN_MOSI 5
#define PIN_MISO 19
#define PIN_SCLK 21
// Send the given byte and return the byte received (mode0)
byte spi_transfer(byte value = 0)
{
// As we shift out outgoing bits out the top bits,
// we shift the incoming bits into the low bits
Serial.print("Sending 0x");
Serial.println(value, HEX);
for (byte i = 0; i < 8; ++i) {
byte b = (value & 0x80U) ? HIGH : LOW;
value <<= 1;
digitalWrite(PIN_MOSI, b);
delayMicroseconds(1000);
digitalWrite(PIN_SCLK, HIGH);
value |= (digitalRead(PIN_MISO) != LOW);
delayMicroseconds(1000);
digitalWrite(PIN_SCLK, LOW);
}
Serial.print("Received 0x");
Serial.println((unsigned)value, HEX);
return value;
}
#define AVRISP_CMD_CHIP_ERASE 0b10000000
#define AVRISP_CMD_WRITE_FUSE 0b01000000
#define AVRISP_CMD_WRITE_LOCK 0b00100000
#define AVRISP_CMD_WRITE_FLASH 0b00010000
#define AVRISP_CMD_WRITE_EEPROM 0b00010001
#define AVRISP_CMD_READ_SIGCAL 0b00001000
#define AVRISP_CMD_READ_FUSE 0b00000100
#define AVRISP_CMD_READ_FLASH 0b00000010
#define AVRISP_CMD_READ_EEPROM 0b00000011
struct isp_cmd {
byte command;
byte addrhi;
byte addrlo;
byte value;
};
byte send_isp_cmd(struct isp_cmd const *cmd, byte *full_reply = nullptr)
{
if (!full_reply) {
spi_transfer(cmd->command);
spi_transfer(cmd->addrhi);
spi_transfer(cmd->addrlo);
return spi_transfer(cmd->value);
}
full_reply[0] = spi_transfer(cmd->command);
full_reply[1] = spi_transfer(cmd->addrhi);
full_reply[2] = spi_transfer(cmd->addrlo);
full_reply[3] = spi_transfer(cmd->value);
return full_reply[3];
}
//byte avrisp_read_sigcal()
//{
//}
byte avrisp_read_fuselock()
{
isp_cmd cmd{0b01010000, 0, 0, 0};
byte fuselock = send_isp_cmd(&cmd);
return fuselock;
}
// Should return 0b01010011
byte avrisp_programming_enable()
{
byte reply[4];
isp_cmd cmd{0b10101100, 0b01010011, 0, 0};
send_isp_cmd(&cmd, reply);
return reply[3];
}
void setup()
{
Serial.begin(115200);
// Must give at least two cycles reset high before pulling reset low,
// if you can't guarantee that reset is initially low
digitalWrite(PIN_RESET, HIGH);
delayMicroseconds(2);
// Pull reset low
// otherwise the device might drive those SPI pins
digitalWrite(PIN_RESET, LOW);
pinMode(PIN_RESET, OUTPUT);
digitalWrite(PIN_MOSI, LOW);
digitalWrite(PIN_MISO, LOW);
digitalWrite(PIN_SCLK, LOW);
pinMode(PIN_MOSI, OUTPUT);
pinMode(PIN_MISO, INPUT);
pinMode(PIN_SCLK, OUTPUT);
// After pulling Reset low, wait at least 20ms before issuing the first command
delayMicroseconds(20000);
Serial.println("Enabling programming");
byte reply = avrisp_programming_enable();
Serial.print("Enable programming reply: ");
Serial.println(reply);
Serial.println("Reading fuselock");
byte fuselock = avrisp_read_fuselock();
Serial.print("Fuse/lock byte: 0x");
Serial.println(fuselock, HEX);
// Tristate everything
// pinMode(PIN_SCLK, INPUT);
// pinMode(PIN_MOSI, INPUT);
// pinMode(PIN_RESET, INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment