summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNicolas Schodet2010-11-29 23:08:04 +0100
committerNicolas Schodet2010-11-29 23:08:04 +0100
commitbfabdf3ed83f75bd36be16e23dda54b5d1e38520 (patch)
treee8cb6864592ba64aec47b80eb319cf25148fca2d
parent74e86e39840c2d83811b01ddc69acecde2b104ab (diff)
digital/dev2: add TWI master module
-rw-r--r--digital/dev2/doc/twi.txt63
-rw-r--r--digital/dev2/src/common/usb_twi.c279
-rw-r--r--digital/dev2/src/common/usb_twi.h37
-rw-r--r--digital/dev2/src/usb_twi/Makefile14
-rw-r--r--digital/dev2/src/usb_twi/avrconfig.h63
-rw-r--r--digital/dev2/src/usb_twi/descriptors.c166
-rw-r--r--digital/dev2/src/usb_twi/descriptors.h36
-rw-r--r--digital/dev2/src/usb_twi/main.c130
-rw-r--r--digital/dev2/tools/dev2/__init__.py0
-rw-r--r--digital/dev2/tools/dev2/twi.py69
10 files changed, 857 insertions, 0 deletions
diff --git a/digital/dev2/doc/twi.txt b/digital/dev2/doc/twi.txt
new file mode 100644
index 00000000..3478b492
--- /dev/null
+++ b/digital/dev2/doc/twi.txt
@@ -0,0 +1,63 @@
+=====================================
+ dev2 twi - Two Wire Interface (I2C)
+=====================================
+
+The twi module provides a master twi controlled by the host.
+
+Do not forget to select an output using the control script!
+
+Controlling using a serial monitor
+==================================
+
+To control twi master, use a serial monitor (minicom, picocom, gtkterm,
+screen, socat...). This module defines a language to make twi requests.
+
+Commands are composed of a command letter, followed by hexadecimal parameters,
+and finally a carriage return.
+
+Protocol errors are signaled using an exclamation mark followed by a carriage
+return.
+
+Sending data
+------------
+
+Command::
+
+ s<slave><data string>\r
+
+Response::
+
+ S<number of bytes sent>\r
+
+For example::
+
+ s04010203\r
+ S03\r
+
+The example sends the bytes 0x01, 0x02 and 0x03 to the slave at address 0x04.
+The modules responded that all three bytes were sent.
+
+Receiving data
+--------------
+
+Command::
+
+ r<slave><number of bytes to receive>\r
+
+Response::
+
+ R<data string>\r
+
+For example::
+
+ r0403\r
+ R010203\r
+
+The example request to read three bytes from the slave at address 0x04. The
+modules responded with the received data.
+
+Controlling using python
+========================
+
+The `dev2.twi` python modules defines the Twi class to easily access the twi
+module.
diff --git a/digital/dev2/src/common/usb_twi.c b/digital/dev2/src/common/usb_twi.c
new file mode 100644
index 00000000..e83a94d9
--- /dev/null
+++ b/digital/dev2/src/common/usb_twi.c
@@ -0,0 +1,279 @@
+/* usb_twi.c */
+/* dev2 - Multi-purpose development board using USB and Ethernet. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+#include "common.h"
+
+#include "usb_twi.h"
+#include "descriptors.h"
+
+#include "modules/twi/twi.h"
+#include "modules/usb/usb.h"
+
+/** Parser steps. */
+enum
+{
+ /** Nothing received yet. */
+ PARSER_WAIT_COMMAND,
+ /** Command received, wait address most significant quartet. */
+ PARSER_WAIT_ADDRESS_MSQ,
+ /** First address quartet received, wait second one. */
+ PARSER_WAIT_ADDRESS_LSQ,
+ /** Wait data or end of line. */
+ PARSER_WAIT_DATA_OR_EOL,
+ /** Wait data second quartet. */
+ PARSER_WAIT_DATA_LSQ,
+};
+
+/** Context. */
+struct usb_twi_t
+{
+ /** Buffer used for transmission or reception. */
+ uint8_t buffer[TWI_BUFFER_SIZE];
+ /** Number of bytes in buffer. */
+ uint8_t buffer_tail;
+ /** Number of bytes sent back to USB. */
+ uint8_t buffer_head;
+ /** Command to execute. */
+ char command;
+ /** Slave address. */
+ uint8_t slave;
+ /** Parser step. */
+ uint8_t parser_step;
+ /** Parser first quartet. */
+ uint8_t parser_msq;
+ /** Output buffer (in case of USB not ready). */
+ char output_buffer[4];
+ /** Position in output buffer of next character to send. */
+ uint8_t output_buffer_head;
+};
+
+/** Global context. */
+struct usb_twi_t usb_twi_global;
+#define ctx usb_twi_global
+
+void
+usb_twi_init (void)
+{
+ twi_init (0xfe);
+}
+
+void
+usb_twi_uninit (void)
+{
+ twi_uninit ();
+}
+
+/** Return non zero if there is characters to send. */
+static uint8_t
+usb_twi_poll (void)
+{
+ return ctx.output_buffer[ctx.output_buffer_head];
+}
+
+/** Output byte to output buffer. */
+static void
+usb_twi_ouput_byte (uint8_t p, uint8_t b)
+{
+ uint8_t i;
+ char c;
+ for (i = 0; i < 2; i++)
+ {
+ c = "0123456789abcdef"[b >> 4];
+ ctx.output_buffer[p++] = c;
+ b <<= 4;
+ }
+}
+
+/** Return a character from the output buffer and reload it from buffer if
+ * needed. */
+static char
+usb_twi_getc (void)
+{
+ char c;
+ uint8_t p;
+ /* Take a character in output buffer. */
+ c = ctx.output_buffer[ctx.output_buffer_head];
+ ctx.output_buffer_head++;
+ /* Reload from buffer if needed. */
+ if (!ctx.output_buffer[ctx.output_buffer_head]
+ && ctx.buffer_head != ctx.buffer_tail)
+ {
+ ctx.output_buffer_head = 0;
+ p = 0;
+ usb_twi_ouput_byte (p, ctx.buffer[ctx.buffer_head++]);
+ p += 2;
+ if (ctx.buffer_head == ctx.buffer_tail)
+ ctx.output_buffer[p++] = '\r';
+ ctx.output_buffer[p] = '\0';
+ }
+ return c;
+}
+
+static uint8_t
+usb_twi_get_hex (char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ else if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else
+ return 0xff;
+}
+
+static uint8_t
+usb_twi_exec (void)
+{
+ uint8_t r, p, l;
+ if (ctx.command == 's')
+ {
+ twi_master_send (ctx.slave, ctx.buffer, ctx.buffer_tail);
+ r = twi_master_wait ();
+ ctx.buffer[0] = r;
+ ctx.buffer_head = 0;
+ ctx.buffer_tail = 1;
+ ctx.output_buffer_head = 0;
+ p = 0;
+ ctx.output_buffer[p++] = 'S';
+ ctx.output_buffer[p++] = '\0';
+ return 1;
+ }
+ else if (ctx.command == 'r' && ctx.buffer_tail == 1)
+ {
+ l = ctx.buffer[0];
+ twi_master_recv (ctx.slave, ctx.buffer, l);
+ r = twi_master_wait ();
+ ctx.buffer_head = 0;
+ ctx.buffer_tail = r;
+ ctx.output_buffer_head = 0;
+ p = 0;
+ ctx.output_buffer[p++] = 'R';
+ if (r == 0)
+ ctx.output_buffer[p++] = '\r';
+ ctx.output_buffer[p++] = '\0';
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static void
+usb_twi_accept (char c)
+{
+ uint8_t q;
+ /* Purge output buffer. */
+ ctx.output_buffer_head = 0;
+ ctx.output_buffer[0] = '\0';
+ /* Accept FSM. */
+ switch (ctx.parser_step)
+ {
+ case PARSER_WAIT_COMMAND:
+ if (c == 's' || c == 'r')
+ {
+ ctx.command = c;
+ ctx.buffer_tail = 0;
+ ctx.parser_step++;
+ return;
+ }
+ break;
+ case PARSER_WAIT_ADDRESS_MSQ:
+ q = usb_twi_get_hex (c);
+ if (q != 0xff)
+ {
+ ctx.parser_msq = q;
+ ctx.parser_step++;
+ return;
+ }
+ break;
+ case PARSER_WAIT_ADDRESS_LSQ:
+ q = usb_twi_get_hex (c);
+ if (q != 0xff)
+ {
+ ctx.slave = ctx.parser_msq << 4 | q;
+ ctx.parser_step++;
+ return;
+ }
+ break;
+ case PARSER_WAIT_DATA_OR_EOL:
+ if (c == '\r')
+ {
+ ctx.parser_step = PARSER_WAIT_COMMAND;
+ if (usb_twi_exec ())
+ return;
+ }
+ else if (ctx.buffer_tail < TWI_BUFFER_SIZE)
+ {
+ q = usb_twi_get_hex (c);
+ if (q != 0xff)
+ {
+ ctx.parser_msq = q;
+ ctx.parser_step++;
+ return;
+ }
+ }
+ break;
+ case PARSER_WAIT_DATA_LSQ:
+ q = usb_twi_get_hex (c);
+ if (q != 0xff)
+ {
+ ctx.buffer[ctx.buffer_tail++] = ctx.parser_msq << 4 | q;
+ ctx.parser_step--;
+ return;
+ }
+ break;
+ }
+ /* If here, there was an error. */
+ ctx.buffer_tail = ctx.buffer_head = 0;
+ ctx.output_buffer_head = 0;
+ ctx.output_buffer[0] = '!';
+ ctx.output_buffer[1] = '\r';
+ ctx.output_buffer[2] = '\0';
+ ctx.parser_step = PARSER_WAIT_COMMAND;
+}
+
+void
+usb_twi_task (void)
+{
+ Endpoint_SelectEndpoint (TWI_RX_EPNUM);
+ /* If data is available from USB: */
+ if (Endpoint_ReadWriteAllowed ())
+ {
+ /* Read as much as possible, and clear endpoint. */
+ do {
+ usb_twi_accept (Endpoint_Read_Byte ());
+ } while (Endpoint_ReadWriteAllowed ());
+ Endpoint_ClearCurrentBank ();
+ }
+ /* If data is available from uart and there is room in the TX endpoint: */
+ Endpoint_SelectEndpoint (TWI_TX_EPNUM);
+ if (usb_twi_poll () && Endpoint_ReadWriteAllowed ())
+ {
+ do {
+ Endpoint_Write_Byte (usb_twi_getc ());
+ } while (usb_twi_poll () && Endpoint_ReadWriteAllowed ());
+ Endpoint_ClearCurrentBank ();
+ }
+}
+
diff --git a/digital/dev2/src/common/usb_twi.h b/digital/dev2/src/common/usb_twi.h
new file mode 100644
index 00000000..ccc227bc
--- /dev/null
+++ b/digital/dev2/src/common/usb_twi.h
@@ -0,0 +1,37 @@
+#ifndef usb_twi_h
+#define usb_twi_h
+/* usb_twi.h */
+/* dev2 - Multi-purpose development board using USB and Ethernet. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+
+void
+usb_twi_init (void);
+
+void
+usb_twi_uninit (void);
+
+void
+usb_twi_task (void);
+
+#endif /* usb_twi_h */
diff --git a/digital/dev2/src/usb_twi/Makefile b/digital/dev2/src/usb_twi/Makefile
new file mode 100644
index 00000000..48a85cfc
--- /dev/null
+++ b/digital/dev2/src/usb_twi/Makefile
@@ -0,0 +1,14 @@
+BASE = ../../../avr
+AVR_PROGS = dev2_twi
+dev2_twi_SOURCES = main.c descriptors.c select.c usb_twi.c
+MODULES = usb twi
+CONFIGFILE = avrconfig.h
+AVR_MCU = at90usb162
+# -O2 : speed
+# -Os : size
+OPTIMIZE = -Os
+
+INCLUDES = -I.. -I.
+vpath %.c ../common
+
+include $(BASE)/make/Makefile.gen
diff --git a/digital/dev2/src/usb_twi/avrconfig.h b/digital/dev2/src/usb_twi/avrconfig.h
new file mode 100644
index 00000000..5c2d92ce
--- /dev/null
+++ b/digital/dev2/src/usb_twi/avrconfig.h
@@ -0,0 +1,63 @@
+#ifndef avrconfig_h
+#define avrconfig_h
+/* avrconfig.h */
+/* dev2 - Multi-purpose development board using USB and Ethernet. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+
+/* utils */
+/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800,
+ * 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */
+#define AC_FREQ 8000000
+
+/* twi - TWI module. */
+/** Driver to implement TWI: HARD, SOFT, or USI. */
+#define AC_TWI_DRIVER SOFT
+/** Do not use interrupts. */
+#define AC_TWI_NO_INTERRUPT 0
+/** TWI frequency, should really be 100 kHz. */
+#define AC_TWI_FREQ 10000
+/** Enable slave part. */
+#define AC_TWI_SLAVE_ENABLE 0
+/** Enable master part. */
+#define AC_TWI_MASTER_ENABLE 1
+/** Use polled slave mode: received data is stored in a buffer which can be
+ * polled using twi_slave_poll. */
+#define AC_TWI_SLAVE_POLLED 1
+/** Slave reception callback to be defined by the user when not in polled
+ * mode. */
+#undef AC_TWI_SLAVE_RECV
+/** Master transfer completion callback, optionally defined by the user, called
+ * at end of master transfer. */
+#undef AC_TWI_MASTER_DONE
+/** Use internal pull up. */
+#define AC_TWI_PULL_UP 1
+/** SDA line IO for SOFT driver. */
+#define AC_TWI_SOFT_SDA_IO D, 7
+/** SCL line IO for SOFT driver. */
+#define AC_TWI_SOFT_SCL_IO D, 5
+
+/* usb */
+#include "modules/usb/lufaconfig.h"
+
+#endif /* avrconfig_h */
diff --git a/digital/dev2/src/usb_twi/descriptors.c b/digital/dev2/src/usb_twi/descriptors.c
new file mode 100644
index 00000000..728184f6
--- /dev/null
+++ b/digital/dev2/src/usb_twi/descriptors.c
@@ -0,0 +1,166 @@
+/* descriptors.c */
+/* dev2 - Multi-purpose development board using USB and Ethernet. {{{
+ *
+ * Copyright (C) 2009 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+#include "common.h"
+
+#include "modules/usb/usb.h"
+
+#include <avr/pgmspace.h>
+
+#include "descriptors.h"
+
+/* Configuration structure. */
+typedef struct
+{
+ USB_Descriptor_Configuration_Header_t Config;
+ USB_Descriptor_Interface_t TS1_Interface;
+ USB_Descriptor_Endpoint_t TS1_DataOutEndpoint;
+ USB_Descriptor_Endpoint_t TS1_DataInEndpoint;
+} USB_Descriptor_Configuration_t;
+
+USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
+{
+ Header: { Size: sizeof (USB_Descriptor_Device_t), Type: DTYPE_Device },
+ USBSpecification: VERSION_BCD (01.10),
+ Class: 0xFF,
+ SubClass: 0x00,
+ Protocol: 0x00,
+ Endpoint0Size: 8,
+ /* Taken from LUFA IDs. */
+ VendorID: 0x03EB,
+ ProductID: 0x204E,
+ ReleaseNumber: 0x0000,
+ ManufacturerStrIndex: 0x01,
+ ProductStrIndex: 0x02,
+ SerialNumStrIndex: NO_DESCRIPTOR,
+ NumberOfConfigurations: 1
+};
+
+USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
+{
+ Config:
+ {
+ Header: { Size: sizeof (USB_Descriptor_Configuration_Header_t),
+ Type: DTYPE_Configuration },
+ TotalConfigurationSize: sizeof (USB_Descriptor_Configuration_t),
+ TotalInterfaces: 1,
+ ConfigurationNumber: 1,
+ ConfigurationStrIndex: NO_DESCRIPTOR,
+ ConfigAttributes: (USB_CONFIG_ATTR_BUSPOWERED |
+ USB_CONFIG_ATTR_SELFPOWERED),
+ MaxPowerConsumption: USB_CONFIG_POWER_MA (100)
+ },
+
+ TS1_Interface:
+ {
+ Header: { Size: sizeof (USB_Descriptor_Interface_t),
+ Type: DTYPE_Interface },
+ InterfaceNumber: 0,
+ AlternateSetting: 0,
+ TotalEndpoints: 2,
+ Class: 0xFF,
+ SubClass: 0x00,
+ Protocol: 0x00,
+ InterfaceStrIndex: NO_DESCRIPTOR
+ },
+
+ TS1_DataOutEndpoint:
+ {
+ Header: { Size: sizeof (USB_Descriptor_Endpoint_t),
+ Type: DTYPE_Endpoint },
+ EndpointAddress: (ENDPOINT_DESCRIPTOR_DIR_OUT | TWI_RX_EPNUM),
+ Attributes: EP_TYPE_BULK,
+ EndpointSize: TWI_RX_EPSIZE,
+ PollingIntervalMS: 0x00
+ },
+
+ TS1_DataInEndpoint:
+ {
+ Header: { Size: sizeof (USB_Descriptor_Endpoint_t),
+ Type: DTYPE_Endpoint },
+ EndpointAddress: (ENDPOINT_DESCRIPTOR_DIR_IN | TWI_TX_EPNUM),
+ Attributes: EP_TYPE_BULK,
+ EndpointSize: TWI_TX_EPSIZE,
+ PollingIntervalMS: 0x00
+ },
+};
+
+USB_Descriptor_String_t PROGMEM LanguageString =
+{
+ Header: { Size: USB_STRING_LEN (1), Type: DTYPE_String },
+ UnicodeString: {LANGUAGE_ID_ENG}
+};
+
+USB_Descriptor_String_t PROGMEM ManufacturerString =
+{
+ Header: { Size: USB_STRING_LEN (7), Type: DTYPE_String },
+ UnicodeString: L"APBTeam"
+};
+
+USB_Descriptor_String_t PROGMEM ProductString =
+{
+ Header: { Size: USB_STRING_LEN (8), Type: DTYPE_String },
+ UnicodeString: L"dev2 twi"
+};
+
+uint16_t
+USB_GetDescriptor (const uint16_t wValue, const uint8_t wIndex,
+ void ** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = wValue >> 8;
+ const uint8_t DescriptorNumber = wValue & 0xFF;
+ void * Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = DESCRIPTOR_ADDRESS (DeviceDescriptor);
+ Size = sizeof (USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = DESCRIPTOR_ADDRESS (ConfigurationDescriptor);
+ Size = sizeof (USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ switch (DescriptorNumber)
+ {
+ case 0x00:
+ Address = DESCRIPTOR_ADDRESS (LanguageString);
+ Size = pgm_read_byte (&LanguageString.Header.Size);
+ break;
+ case 0x01:
+ Address = DESCRIPTOR_ADDRESS (ManufacturerString);
+ Size = pgm_read_byte (&ManufacturerString.Header.Size);
+ break;
+ case 0x02:
+ Address = DESCRIPTOR_ADDRESS (ProductString);
+ Size = pgm_read_byte (&ProductString.Header.Size);
+ break;
+ }
+ break;
+ }
+ *DescriptorAddress = Address;
+ return Size;
+}
+
diff --git a/digital/dev2/src/usb_twi/descriptors.h b/digital/dev2/src/usb_twi/descriptors.h
new file mode 100644
index 00000000..e63cafc4
--- /dev/null
+++ b/digital/dev2/src/usb_twi/descriptors.h
@@ -0,0 +1,36 @@
+#ifndef descriptors_h
+#define descriptors_h
+/* descriptors.h */
+/* dev2 - Multi-purpose development board using USB and Ethernet. {{{
+ *
+ * Copyright (C) 2009 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+
+/* Endpoints. */
+#define TWI_TX_EPNUM 1
+#define TWI_TX_EPSIZE 16
+#define TWI_RX_EPNUM 2
+#define TWI_RX_EPSIZE 16
+
+#define TWI_BUFFER_SIZE 128
+
+#endif /* descriptors_h */
diff --git a/digital/dev2/src/usb_twi/main.c b/digital/dev2/src/usb_twi/main.c
new file mode 100644
index 00000000..fa1f2b98
--- /dev/null
+++ b/digital/dev2/src/usb_twi/main.c
@@ -0,0 +1,130 @@
+/* main.c */
+/* dev2 - Multi-purpose development board using USB and Ethernet. {{{
+ *
+ * Copyright (C) 2009 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+#include "common.h"
+
+#include "modules/usb/usb.h"
+#include "io.h"
+
+#include <avr/wdt.h>
+
+#include "descriptors.h"
+#include "common/usb_twi.h"
+#include "common/select.h"
+
+HANDLES_EVENT (USB_Connect);
+HANDLES_EVENT (USB_Disconnect);
+HANDLES_EVENT (USB_ConfigurationChanged);
+HANDLES_EVENT (USB_UnhandledControlPacket);
+
+volatile uint8_t usb_connected, usb_configured;
+
+int
+main (void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses. */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable ();
+ /* Disable Clock Division. */
+ SetSystemClockPrescaler (0);
+ /* Initialise hardware. */
+ select_init ();
+ /* Initialize USB Subsystem. */
+ USB_Init ();
+ /* Main loop. */
+ while (1)
+ {
+ if (usb_connected)
+ USB_USBTask ();
+ if (usb_configured)
+ {
+ usb_twi_task ();
+ }
+ }
+}
+
+EVENT_HANDLER (USB_Connect)
+{
+ usb_connected = 1;
+}
+
+EVENT_HANDLER (USB_Disconnect)
+{
+ usb_connected = 0;
+ usb_configured = 0;
+}
+
+EVENT_HANDLER (USB_ConfigurationChanged)
+{
+ /* Setup Rx and Tx Endpoints for the first port. */
+ Endpoint_ConfigureEndpoint (TWI_TX_EPNUM, EP_TYPE_BULK,
+ ENDPOINT_DIR_IN, TWI_TX_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+ Endpoint_ConfigureEndpoint (TWI_RX_EPNUM, EP_TYPE_BULK,
+ ENDPOINT_DIR_OUT, TWI_RX_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+ /* Start tasks. */
+ usb_configured = 1;
+}
+
+EVENT_HANDLER (USB_UnhandledControlPacket)
+{
+ /* Process TS specific control requests. */
+ switch (bRequest)
+ {
+ /* Switch back to DFU mode. */
+ case 0:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR |
+ REQREC_DEVICE))
+ {
+ Endpoint_ClearSetupReceived ();
+ /* Send acknowledgement and wait for it to be sent. */
+ Endpoint_ClearSetupIN ();
+ while (!Endpoint_IsSetupINReady ())
+ ;
+ USB_ShutDown ();
+ /* Jump to bootloader. */
+ ((void (*) (void)) 0x3000) ();
+ }
+ break;
+ /* Select output. */
+ case 1:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR |
+ REQREC_DEVICE))
+ {
+ /* Selector parameter. */
+ uint8_t output = Endpoint_Read_Byte ();
+ Endpoint_ClearSetupReceived ();
+ /* Select output. */
+ usb_twi_uninit ();
+ select_out (output);
+ if (select_active (output))
+ usb_twi_init ();
+ /* Send acknowledgement. */
+ Endpoint_ClearSetupIN ();
+ }
+ break;
+ }
+}
+
diff --git a/digital/dev2/tools/dev2/__init__.py b/digital/dev2/tools/dev2/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/digital/dev2/tools/dev2/__init__.py
diff --git a/digital/dev2/tools/dev2/twi.py b/digital/dev2/tools/dev2/twi.py
new file mode 100644
index 00000000..167d2b39
--- /dev/null
+++ b/digital/dev2/tools/dev2/twi.py
@@ -0,0 +1,69 @@
+# dev2 - Multi-purpose development board using USB and Ethernet. {{{
+#
+# Copyright (C) 2010 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# 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 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""TWI interface."""
+
+import binascii
+import struct
+
+class ProtocolError (RuntimeError):
+ pass
+
+class Twi:
+ """Interface to dev2 twi module."""
+
+ def __init__ (self, fd):
+ """Initialise and set file object to use."""
+ self.fd = fd
+
+ def _send_command (self, s):
+ """Send command to dev2, return response."""
+ self.fd.write (s)
+ r = self.fd.readline (eol = '\r')
+ if '!' in r:
+ raise ProtocolError
+ else:
+ return r
+
+ def send (self, address, data):
+ """Send data to specified slave address."""
+ s = ''.join (('s%02x' % address, binascii.hexlify (data), '\r'))
+ r = self._send_command (s)
+ if len (r) != 4 or r[0] != 'S' or r[-1] != '\r':
+ raise ProtocolError
+ try:
+ return int (r[1:-1], 16)
+ except ValueError:
+ raise ProtocolError
+
+ def recv (self, address, size):
+ """Receive data from specified slave address."""
+ s = 'r%02x%02x\r' % (address, size)
+ r = self._send_command (s)
+ if len (r) < 2 or r[0] != 'R' or r[-1] != '\r':
+ raise ProtocolError
+ try:
+ return binascii.unhexlify (r[1:-1])
+ except TypeError:
+ raise ProtocolError
+