summaryrefslogtreecommitdiff
path: root/avr
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2016-01-24 20:02:30 +0100
committerFlorian Jung <flo@windfisch.org>2016-01-24 20:02:30 +0100
commit07ce2df5da6265702e1d99556f46139f8b5b8611 (patch)
tree47a678a8806b3def6b95e84f9f6f10e2f5c813bb /avr
parentdfc2f5fbfb5bb34d43fee7677486d8e8430f1f87 (diff)
write/verify scratchpad. proper formatting. warning comment.
Diffstat (limited to 'avr')
-rw-r--r--avr/1wire.c63
-rw-r--r--avr/1wire.h4
-rw-r--r--avr/main.c67
3 files changed, 125 insertions, 9 deletions
diff --git a/avr/1wire.c b/avr/1wire.c
index affd80d..54c8dcc 100644
--- a/avr/1wire.c
+++ b/avr/1wire.c
@@ -6,6 +6,30 @@
/* danni@specs.de */
/* */
/************************************************************************/
+
+/* modified by Florian Jung (flo@windfisch.org).
+ * Changelog:
+ * - try to drive parasite-powered devices via avr-builtin pullup
+ * - DS199X access functions
+ */
+
+/* WARNING WARNING WARNING:
+ * this code VIOLATES THE 1-WIRE SPECIFICATION! Instead of "letting the
+ * line float" (which implies that it's gently pulled up to 5V by the
+ * pullup resistor), we're hard connecting the line against +5V, without
+ * any resistor in between. After some time, we let the line float, only
+ * held up by the (weak) AVR-internal pullup.
+ *
+ * THIS COULD DESTROY YOUR HARDWARE! you have been warned.
+ *
+ * (We do this because the internal pullup isn't strong enough to serve
+ * the DS1992 with power. The line is only hard-connected to +5V, when
+ * we're (sort of) sure that the DS1992 won't pull down the line to GND
+ * (since that would cause a short-circuit). Buuuut there's no guarantee,
+ * it just works[tm])
+ */
+
+
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
@@ -176,6 +200,45 @@ void ds1992_read(uint16_t addr, uint8_t* buf, uint8_t len)
buf[i] = w1_byte_rd();
}
+void ds1992_scratch_write(uint16_t addr, const uint8_t* buf, uint8_t len)
+{
+ w1_byte_wr(SKIP_ROM);
+ w1_byte_wr(0x0F); // write scratchpad
+ w1_byte_wr((addr & 0x00FF));
+ w1_byte_wr((addr & 0xFF00) >> 8);
+ for (int i=0; i < len; i++)
+ w1_byte_wr(buf[i]);
+}
+
+uint8_t ds1992_scratch_verify(uint16_t addr, const uint8_t* buf, uint8_t len, uint8_t* es_reg_ptr)
+{
+ uint8_t status = 0;
+
+ w1_byte_wr(SKIP_ROM);
+ w1_byte_wr(0xAA); // read scratchpad
+
+ // check address bytes
+ if (w1_byte_rd() != (addr & 0x00FF)) status |= 0x01;
+ if (w1_byte_rd() != (addr & 0xFF00) >> 8) status |= 0x02;
+
+ uint8_t es_reg = w1_byte_rd();
+ *es_reg_ptr = es_reg;
+ // check E/S register
+ if (es_reg & 0x20) // PF: partial byte flag
+ status |= 0x04;
+ if (es_reg & 0x40) // OF: overflow flag
+ status |= 0x08;
+ if ((es_reg & 0x1F) != (addr & 0x1F) + (len-1))
+ status |= 0x10;
+
+ for (int i=0; i < len; i++)
+ if (w1_byte_rd() != buf[i])
+ status |= 0xF0;
+
+ return status;
+}
+
+
void w1_command( uint8_t command, uint8_t *id )
{
uint8_t i;
diff --git a/avr/1wire.h b/avr/1wire.h
index accb132..af48d0b 100644
--- a/avr/1wire.h
+++ b/avr/1wire.h
@@ -24,4 +24,8 @@ uint8_t w1_byte_rd( void );
uint8_t w1_rom_search( uint8_t diff, uint8_t*id );
void w1_command( uint8_t command, uint8_t *id );
+
+void ds1992_read(uint16_t addr, uint8_t* buf, uint8_t len);
+void ds1992_scratch_write(uint16_t addr, const uint8_t* buf, uint8_t len);
+uint8_t ds1992_scratch_verify(uint16_t addr, const uint8_t* buf, uint8_t len, uint8_t* es_reg_ptr);
#endif
diff --git a/avr/main.c b/avr/main.c
index 6774d6e..15d98d3 100644
--- a/avr/main.c
+++ b/avr/main.c
@@ -55,6 +55,8 @@ void jump_to_bootloader(void)
}
static uchar replyBuffer[130]="Hello world initial";
+static uchar buf[33];
+
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *) data;
@@ -152,28 +154,75 @@ int main(void)
sei(); // Enable interrupts after re-enumeration
+ uint8_t error = 0;
while (1)
{
wdt_reset(); // keep the watchdog happy
usbPoll();
- if (++c % (got_data ? 1000 : 3000) == 0)
+ if (++c % (error ? 12000 : got_data ? 1000 : 3000) == 0)
{
PORTC^=LED_BLUE;
PORTC |= LED_RED | LED_GREEN;
}
if (c % 12000 == 0)
{
- uint8_t result = w1_reset();
- if (result == 0) // device detected
+ 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*!)
{
- PORTC &= ~LED_GREEN;
- ds1992_read(0, replyBuffer, 128);
+ 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;
+ }
+
+ 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);
}
- else if (result == 1) // no presence pulse == no device detected
- PORTC &= ~LED_RED;
- else // short circuit detected
- PORTC &= ~(LED_RED | LED_GREEN);
}
}