/*
Project: DS1992 memory iButton dumper
Author: Florian Jung (flo@windfisch.org)
Copyright: (c) 2015 by Florian Jung
License: GNU GPL v3 (see LICENSE)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
This project is based on the code for the AVR ATtiny USB Tutorial at
http://codeandlife.com/ by Joonas Pihlajamaa, joonas.pihlajamaa@iki.fi,
which is in turn based on the V-USB example code by Christian Starkjohann
(Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH)
*/
/* this project is designed for the USB AVR LAB board by ullihome
* (http://www.ullihome.de/wiki/USBAVRLab/index)
* That's a small Atmega8-powered board with software-USB and a small pinout
* that looks like this:
* ____ ____ ____ ____
* | . . . . . | | o . . . . |
* | . . . . . | or | x . . . . |
* |___________| |___________|
*
* hold the DS1992 token against the pins, so that the outer ring touches the
* "x" pin, while the inner circle touches the "o" pin.
*
* How to use:
* the dumping device has three modes of operation, which are shown by the blinking
* speed of the blue LED.
* 1. reading mode: normal blinking
* 2. reading mode: slooow blinking (previous operation failed)
* 3. writing mode: fast blinking
*
* in either mode, the red LED flashes periodically. This means that the device
* probed for a DS1992, but couldn't find anything on the bus. If you hold you
* DS1992 against the pins, the flashing will turn green instead. This means that
* the token has been read into the device's RAM.
* You can now use `pc/a.out read` to read the contents.
* (If both green and red leds flash, this means you've a short circuit.)
*
* If you execute `pc/a.out write `, then the device will enter
* writing mode. The flashing red LED has the same meaning as before. If you now
* connect the token, the page (1-indexed) will be written to with ,
* whenever the LED flashes green the next time.
* After that, the device enters reading mode again. If the LED blinks really slow,
* then there was a write error. re-execute a.out write, reconnect the token and retry.
* Additionally, after writing you can use `a.out read` again (without connecting the
* token for reading previously). This will output you a lot of garbage, but the first
* byte read tells you a more detailed error code:
* 0x01: "reset/presence pulse" failed after scratchpad write
* 0x02: scratchpad did not verify correctly
* 0x03: "reset/presence pulse" failed after scratchpad readback + verify
* 0xFF: probably successful
*
* Note that you should read back the data after writing, just to be sure.
* Also note that while you can read the whole memory at once, you must execute the write
* command, and also connect the token, four times for a full write (once for each page).
*/
#include
#include
#include
#include
#include
#include
#include "usbdrv/usbdrv.h"
#include "1wire.h"
#define LED_BLUE (1<<5)
#define LED_RED (1<<4)
#define LED_GREEN (1<<3)
#define FUNC_READ 0x42
#define FUNC_WRITE 0x21
#define FUNC_START_BOOTLOADER 30
#define FUNC_GET_TYPE 0xFE
volatile int got_data = 0; // set to 1, if we get data to write from the PC
volatile int recvd_data_len = 0;
void jump_to_bootloader(void)
{
cli();
wdt_enable(WDTO_15MS);
while (1);
}
static uchar replyBuffer[130]="Hello world initial";
static uchar buf[33];
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *) data;
int len = 1;
switch (rq->bRequest)
{
case FUNC_GET_TYPE:
replyBuffer[0]=10;
len = 1;
break;
case FUNC_START_BOOTLOADER:
jump_to_bootloader();
len = 0;
break;
case FUNC_READ:
recvd_data_len = 0;
return USB_NO_MSG;
case FUNC_WRITE:
PORTC ^= LED_RED;
//strcpy(replyBuffer, "Hello world");
//len = strlen(replyBuffer)+1;
len = 130;
break;
}
usbMsgPtr = replyBuffer;
return len;
}
volatile int count = 5;
uchar usbFunctionWrite(uint8_t * data, uchar len)
{
memcpy(replyBuffer+recvd_data_len,data,len);
recvd_data_len+=len;
if (recvd_data_len >= 33)
got_data = 1;
//replyBuffer[len]='\0';
return len;
}
void usb_disconnect()
{
USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT);
usbDeviceDisconnect();
}
void usb_reconnect()
{
cli();
usbDeviceDisconnect(); // enforce re-enumeration
for (int i = 0; i < 250; i++)
{ // wait 500 ms
wdt_reset(); // keep the watchdog happy
_delay_ms(10);
}
usbDeviceConnect();
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
sei();
}
int main(void)
{
uint32_t c = 0;
DDRC = 0x38; // LEDs as output
PORTC |= LED_BLUE | LED_RED | LED_GREEN;
DDRD &= ~0xF3; // connector ports as input
DDRB &= ~0x3C;
PORTD &= ~0xF3; // disable pullups for unused ports
PORTB &= ~0x0C;
PORTB |= 0x30; // enable pullups for PB4 and 5
replyBuffer[129] = 0;
cli();
wdt_enable(WDTO_1S); // enable 1s watchdog timer
usbInit();
usbDeviceDisconnect(); // enforce re-enumeration
for (int i = 0; i < 250; i++)
{ // wait 500 ms
wdt_reset(); // keep the watchdog happy
_delay_ms(10);
}
usbDeviceConnect();
sei(); // Enable interrupts after re-enumeration
uint8_t error = 0;
while (1)
{
wdt_reset(); // keep the watchdog happy
usbPoll();
if (++c % (error ? 12000 : got_data ? 1000 : 3000) == 0)
{
PORTC^=LED_BLUE;
PORTC |= LED_RED | LED_GREEN;
}
if (c % 12000 == 0)
{
if (!got_data) // we want to read the token
{
uint8_t result = w1_reset();
if (result == 0) // device detected
{
PORTC &= ~LED_GREEN;
ds1992_read(0, replyBuffer, 128);
}
else if (result == 1) // no presence pulse == no device detected
PORTC &= ~LED_RED;
else // short circuit detected
PORTC &= ~(LED_RED | LED_GREEN);
}
else // we want to WRITE the token (*shudder*!)
{
uint8_t result = w1_reset();
if (result == 0) // device detected
{
PORTC &= ~LED_GREEN;
cli();
memcpy(buf, replyBuffer, 33);
got_data = 0;
sei();
uint16_t writepos = ((uint16_t)buf[32]) * 32;
ds1992_scratch_write(writepos, buf, 32);
result = w1_reset();
if (result != 0)
{
replyBuffer[0] = 0x01;
error = 1;
goto write_failed;
}
uint8_t es_reg;
result = ds1992_scratch_verify(writepos, buf, 32, &es_reg);
if (result != 0)
{
replyBuffer[0] = 0x02;
error = 1;
goto write_failed;
}
result = w1_reset();
if (result != 0)
{
replyBuffer[0] = 0x03;
error = 1;
goto write_failed;
}
// commit the write
ds1992_scratch_copy(writepos, es_reg);
replyBuffer[0] = 0xFF; // success
error = 0;
write_failed:
1;
}
else if (result == 1) // no presence pulse == no device detected
PORTC &= ~LED_RED;
else // short circuit detected
PORTC &= ~(LED_RED | LED_GREEN);
}
}
}
jump_to_bootloader();
return 0;
}