/* 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; }