diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-03-11 13:59:31 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-03-11 13:59:31 +0000 |
commit | 89a38d4273a9ef6f7e2d46876ddfe5ce8cee10da (patch) | |
tree | c3707e992cf53ddf71410e75eab4a35ed97defcc /firmware/target | |
parent | 04ea446edc56d0891f458ffa8f2b0e2616e443df (diff) | |
download | rockbox-89a38d4273a9ef6f7e2d46876ddfe5ce8cee10da.tar.gz rockbox-89a38d4273a9ef6f7e2d46876ddfe5ce8cee10da.zip |
iAudio X5: Enable reading of DS2411 serial number. See it under System|Debug|View HW info.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12723 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/coldfire/iaudio/x5/ds2411-x5.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/firmware/target/coldfire/iaudio/x5/ds2411-x5.c b/firmware/target/coldfire/iaudio/x5/ds2411-x5.c new file mode 100644 index 0000000000..a8b2ae705c --- /dev/null +++ b/firmware/target/coldfire/iaudio/x5/ds2411-x5.c @@ -0,0 +1,206 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 by Michael Sevakis + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include "system.h" +#include "cpu.h" +#include "ds2411.h" +#include "logf.h" + +/* Delay factor that depends on CPU frequency */ +static unsigned int ds2411_delay_factor = 0; + +#define DS2411_BIT (1 << 22) + +/* Delay the specified number of microseconds - plus a tiny bit */ +#define DELAY(uS) \ + asm volatile( \ + "move.l %[x], %%d0 \n" \ + "mulu.l %[factor], %%d0 \n" \ + "1: \n" \ + "subq.l #1, %%d0 \n" \ + "bhi.s 1b \n" \ + : : [factor]"d"(ds2411_delay_factor), [x]"d"(uS) : "d0"); + +/* Calculate the CRC of a byte */ +static unsigned char ds2411_calc_crc(unsigned char byte) +{ + /* POLYNOMIAL = X^8 + X^5 + X^4 + 1 */ + static const unsigned char eor[8] = + { + 0x5e, /* 01011110 */ + 0xbc, /* 10111100 */ + 0x61, /* 01100001 */ + 0xc2, /* 11000010 */ + 0x9d, /* 10011101 */ + 0x23, /* 00100011 */ + 0x46, /* 01000110 */ + 0x8c, /* 10001100 */ + }; + + unsigned char crc = 0; + int i = 0; + + do + { + if (byte & (1 << i)) + crc ^= eor[i]; + } + while (++i < 8); + + return crc; +} /* ds2411_calc_crc */ + +/* Write a byte to the DS2411 - LSb first */ +static void ds2411_write_byte(unsigned char data) +{ + int i = 0; + + do + { + if (data & 0x01) + { + /* Write a "1": Hold line low, then leave line pulled up and wait + out the remainder of Tslot */ + or_l(DS2411_BIT, &GPIO_ENABLE); + DELAY(6); + and_l(~DS2411_BIT, &GPIO_ENABLE); + DELAY(60); + } + else + { + /* Write a "0": Hold line low, then leave line pulled up and wait + out the remainder of Tslot which is just Trec */ + or_l(DS2411_BIT, &GPIO_ENABLE); + DELAY(60); + and_l(~DS2411_BIT, &GPIO_ENABLE); + DELAY(6); + } + + data >>= 1; + } + while (++i < 8); +} /* ds2411_write_byte */ + +/* Read a byte from the DS2411 - LSb first */ +static unsigned char ds2411_read_byte(void) +{ + int i = 0; + unsigned data = 0; + + do + { + /* Hold line low to begin bit read: Tf + Trl */ + or_l(DS2411_BIT, &GPIO_ENABLE); + DELAY(6); + + /* Set line high and delay before sampling within the master + sampling window: Tmsr - max 15us from Trl start */ + and_l(~DS2411_BIT, &GPIO_ENABLE); + DELAY(9); + + /* Sample data line */ + if ((GPIO_READ & DS2411_BIT) != 0) + data |= 1 << i; + + /* Wait out the remainder of Tslot */ + DELAY(60); + } + while (++i < 8); + + return data; +} /* ds2411_read_byte */ + +/* + * Byte 0: 8-bit family code (01h) + * Bytes 1-6: 48-bit serial number + * Byte 7: 8-bit CRC code + */ +int ds2411_read_id(struct ds2411_id *id) +{ + int i; + unsigned char crc; + + /* Initialize delay factor based on loop time: 3*(uS-1) + 3 */ + ds2411_delay_factor = MIN(cpu_frequency / (1000000*3), 1); + + /* Init GPIO 1 wire bus for bit banging with a pullup resistor where + * it is set low as output and switched between input and output mode. + * Required for bidirectional communication on a single wire. + */ + or_l(DS2411_BIT, &GPIO_FUNCTION); /* Set pin as GPIO */ + and_l(~DS2411_BIT, &GPIO_ENABLE); /* Set as input */ + and_l(~DS2411_BIT, &GPIO_OUT); /* Set low when set as output */ + + /* Delay 100us to stabilize */ + DELAY(100); + + /* Issue reset pulse - 480uS or more to ensure standard (not overdrive) + mode - we don't have the timing accuracy for that. */ + or_l(DS2411_BIT, &GPIO_ENABLE); + /* Delay 560us: (Trstlmin + Trstlmax) / 2*/ + DELAY(560); + and_l(~DS2411_BIT, &GPIO_ENABLE); + /* Delay 66us: Tpdhmax + 6 */ + DELAY(66); + + /* Read presence pulse - line should be pulled low at proper time by the + slave device */ + if (GPIO_READ & DS2411_BIT) + { + logf("ds2411: no presence pulse"); + return DS2411_NO_PRESENCE; + } + + /* Trsth + 1 - 66 = Tpdhmax + Tpdlmax + Trecmin + 1 - 66 */ + DELAY(240); + + /* ds2411 should be ready for data transfer */ + + /* Send Read ROM command */ + ds2411_write_byte(0x33); + + /* Read ROM serial number and CRC */ + i = 0, crc = 0; + + do + { + unsigned char byte = ds2411_read_byte(); + ((unsigned char *)id)[i] = byte; + crc = ds2411_calc_crc(crc ^ byte); + } + while (++i < 8); + + /* Check that family code is ok */ + if (id->family_code != 0x01) + { + logf("ds2411: invalid family code=%02X", (unsigned)id->family_code); + return DS2411_INVALID_FAMILY_CODE; + } + + /* Check that CRC was ok */ + if (crc != 0) /* Because last loop eors the CRC with the resulting CRC */ + { + logf("ds2411: invalid CRC=%02X", (unsigned)id->crc); + return DS2411_INVALID_CRC; + } + + /* Good ID read */ + return DS2411_OK; +} /* ds2411_read_id */ |