rockbox/firmware/target/coldfire/iaudio/x5/ds2411-x5.c
Daniel Stenberg 2acc0ac542 Updated our source code header to explicitly mention that we are GPL v2 or
later. We still need to hunt down snippets used that are not. 1324 modified
files...
http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
2008-06-28 18:10:04 +00:00

216 lines
6.1 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2007 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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,d"(ds2411_delay_factor), [x]"r,i"(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 level = disable_irq_save(); /* Timing sensitive */
int i;
unsigned char crc;
/* Initialize delay factor based on loop time: 3*(uS-1) + 3 */
ds2411_delay_factor = MAX(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) == 0)
{
/* 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);
i = DS2411_INVALID_FAMILY_CODE;
}
/* Check that CRC was ok */
else if (crc != 0) /* Because last loop eors the CRC with the resulting CRC */
{
logf("ds2411: invalid CRC=%02X", (unsigned)id->crc);
i = DS2411_INVALID_CRC;
}
else
{
/* Good ID read */
i = DS2411_OK;
}
}
else
{
logf("ds2411: no presence pulse");
i = DS2411_NO_PRESENCE;
}
restore_irq(level);
return i;
} /* ds2411_read_id */