summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2016-01-09 21:58:53 +0100
committerDaniel Friesel <derf@finalrewind.org>2016-01-09 21:58:53 +0100
commit554d78c9c73731705ab536e009ef47760dd2df3f (patch)
tree03637579a0c1ffc9df25181d5f2bf201bb9be91f
parent3541c176f24f8daee3b0bc35f71e1521daa7137a (diff)
move software I2C implementation to ATTiny
-rw-r--r--commandline/i2c-util.c70
-rw-r--r--commandline/i2c-util.h7
-rw-r--r--commandline/i2cdetect.c6
-rw-r--r--commandline/i2cget.c22
-rw-r--r--commandline/i2cset.c14
-rw-r--r--firmware/main.c99
-rw-r--r--global_config.h7
7 files changed, 187 insertions, 38 deletions
diff --git a/commandline/i2c-util.c b/commandline/i2c-util.c
index 03b2fad..3608e36 100644
--- a/commandline/i2c-util.c
+++ b/commandline/i2c-util.c
@@ -308,6 +308,24 @@ unsigned char i2c_tx_byte(unsigned char byte)
return ack;
}
+unsigned char i2c_hw_tx_byte(unsigned char byte)
+{
+ unsigned char buffer[8];
+
+ int nBytes = usb_control_msg(handle,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USBCMD_TX, 0, byte,
+ (char *)buffer, sizeof(buffer), 5000);
+
+ if (nBytes < 1) {
+ fprintf(stderr, "ERR: tx: got %d bytes, expected 1\n",
+ nBytes);
+ exit(1);
+ }
+
+ return buffer[0];
+}
+
unsigned char i2c_rx_byte(unsigned char send_ack)
{
signed char i;
@@ -330,6 +348,24 @@ unsigned char i2c_rx_byte(unsigned char send_ack)
return ret;
}
+unsigned char i2c_hw_rx_byte(unsigned char send_ack)
+{
+ unsigned char buffer[8];
+
+ int nBytes = usb_control_msg(handle,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USBCMD_RX, 0, send_ack,
+ (char *)buffer, sizeof(buffer), 5000);
+
+ if (nBytes < 1) {
+ fprintf(stderr, "ERR: tx: got %d bytes, expected 1\n",
+ nBytes);
+ exit(1);
+ }
+
+ return buffer[0];
+}
+
void i2c_start()
{
set_sda(1);
@@ -342,6 +378,17 @@ void i2c_start()
verify_scl_low();
}
+void i2c_hw_start()
+{
+ // discarded
+ unsigned char buffer[8];
+
+ usb_control_msg(handle,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USBCMD_START, 0, 0,
+ (char *)buffer, sizeof(buffer), 5000);
+}
+
void i2c_stop()
{
set_scl(1);
@@ -352,6 +399,17 @@ void i2c_stop()
verify_sda_high();
}
+void i2c_hw_stop()
+{
+ // discarded
+ unsigned char buffer[8];
+
+ usb_control_msg(handle,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USBCMD_STOP, 0, 0,
+ (char *)buffer, sizeof(buffer), 5000);
+}
+
void i2c_init()
{
usb_init();
@@ -365,6 +423,18 @@ void i2c_init()
USBDEV_VERSION_MAJOR, USBDEV_VERSION_MINOR);
exit(1);
}
+ i2c_hw_setbits();
+}
+
+void i2c_hw_setbits()
+{
+ // discarded
+ unsigned char buffer[8];
+
+ usb_control_msg(handle,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USBCMD_SETBITS, 0, ((1 << bit_scl) << 8) | (1 << bit_sda),
+ (char *)buffer, sizeof(buffer), 5000);
}
void i2c_deinit()
diff --git a/commandline/i2c-util.h b/commandline/i2c-util.h
index 9be466a..0f47b6e 100644
--- a/commandline/i2c-util.h
+++ b/commandline/i2c-util.h
@@ -10,8 +10,15 @@ unsigned char get_status();
unsigned char i2c_tx_byte(unsigned char byte);
unsigned char i2c_rx_byte(unsigned char send_ack);
+unsigned char i2c_hw_tx_byte(unsigned char byte);
+unsigned char i2c_hw_rx_byte(unsigned char send_ack);
+
void i2c_getopt(int argc, char **argv);
void i2c_start();
void i2c_stop();
void i2c_init();
void i2c_deinit();
+
+void i2c_hw_setbits();
+void i2c_hw_start();
+void i2c_hw_stop();
diff --git a/commandline/i2cdetect.c b/commandline/i2cdetect.c
index 88e5d2e..341900f 100644
--- a/commandline/i2cdetect.c
+++ b/commandline/i2cdetect.c
@@ -24,9 +24,9 @@ int main(int argc, char **argv)
}
- i2c_start();
+ i2c_hw_start();
- if (i2c_tx_byte(i2cid))
+ if (i2c_hw_tx_byte(i2cid))
printf(" %02x", id);
else
fputs(" --", stdout);
@@ -35,7 +35,7 @@ int main(int argc, char **argv)
fputs("\n", stdout);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 0;
}
diff --git a/commandline/i2cget.c b/commandline/i2cget.c
index 9ed8bbd..f2bdb15 100644
--- a/commandline/i2cget.c
+++ b/commandline/i2cget.c
@@ -25,11 +25,11 @@ int main(int argc, char **argv)
}
i2c_init();
- i2c_start();
+ i2c_hw_start();
- if (!i2c_tx_byte((address << 1) | 0)) {
+ if (!i2c_hw_tx_byte((address << 1) | 0)) {
fprintf(stderr, "Received NAK from slave 0x%02x, aborting\n", address);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 3;
}
@@ -38,29 +38,29 @@ int main(int argc, char **argv)
cmdbuf = strtol(argv[i], &conv_err, 0);
if (conv_err && *conv_err) {
fprintf(stderr, "read command: Conversion error at '%s'\n", conv_err);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 2;
}
- if (!i2c_tx_byte(cmdbuf)) {
+ if (!i2c_hw_tx_byte(cmdbuf)) {
fprintf(stderr, "Received NAK after byte %d (0x%02x)\n", i-1, cmdbuf);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 4;
}
}
- i2c_start();
- if (!i2c_tx_byte((address << 1) | 1)) {
+ i2c_hw_start();
+ if (!i2c_hw_tx_byte((address << 1) | 1)) {
fprintf(stderr, "Received NAK after reSTART from slave 0x%02x, aborting\n", address);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 3;
}
- ret = i2c_rx_byte(0);
+ ret = i2c_hw_rx_byte(0);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
printf("%i\n", ret);
diff --git a/commandline/i2cset.c b/commandline/i2cset.c
index 2d7567f..bdcd3cc 100644
--- a/commandline/i2cset.c
+++ b/commandline/i2cset.c
@@ -24,11 +24,11 @@ int main(int argc, char **argv)
}
i2c_init();
- i2c_start();
+ i2c_hw_start();
- if (!i2c_tx_byte(address << 1)) {
+ if (!i2c_hw_tx_byte(address << 1)) {
fprintf(stderr, "Received NAK from slave 0x%02x, aborting\n", address);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 3;
}
@@ -37,19 +37,19 @@ int main(int argc, char **argv)
cmdbuf = strtol(argv[i], &conv_err, 0);
if (conv_err && *conv_err) {
fprintf(stderr, "write command: conversion error at '%s'\n", conv_err);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 2;
}
- if (!i2c_tx_byte(cmdbuf)) {
+ if (!i2c_hw_tx_byte(cmdbuf)) {
fprintf(stderr, "Received NAK after byte %d (0x%02x)\n", i-1, cmdbuf);
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 4;
}
}
- i2c_stop();
+ i2c_hw_stop();
i2c_deinit();
return 0;
diff --git a/firmware/main.c b/firmware/main.c
index 0410134..d04159a 100644
--- a/firmware/main.c
+++ b/firmware/main.c
@@ -33,23 +33,90 @@ Application examples:
USB_PUBLIC uchar usbFunctionSetup(uchar data[8])
{
-usbRequest_t *rq = (void *)data;
-static uchar replyBuf[2];
+ usbRequest_t *rq = (void *)data;
+ static uchar replyBuf[2];
+ static uchar bv_sda, bv_scl, i, buf;
- usbMsgPtr = replyBuf;
- if(rq->bRequest == USBCMD_ECHO) { /* ECHO */
- replyBuf[0] = rq->wValue.bytes[0];
- replyBuf[1] = rq->wValue.bytes[1];
- return 2;
- }
- if(rq->bRequest == USBCMD_GETPORT) { /* GET_STATUS -> result = 1 bytes */
- replyBuf[0] = PINB;
- return 1;
- }
- if(rq->bRequest == USBCMD_SETPORT) { /* SET_STATUS. Payload byte is output. */
- DDRB = ~(rq->wIndex.bytes[0]);
- }
- return 0;
+ usbMsgPtr = replyBuf;
+ if (rq->bRequest == USBCMD_ECHO) {
+ replyBuf[0] = rq->wValue.bytes[0];
+ replyBuf[1] = rq->wValue.bytes[1];
+ return 2;
+ }
+ if (rq->bRequest == USBCMD_GETPORT) {
+ replyBuf[0] = PINB;
+ return 1;
+ }
+ if (rq->bRequest == USBCMD_SETPORT) {
+ DDRB = ~(rq->wIndex.bytes[0]);
+ return 0;
+ }
+ if (rq->bRequest == USBCMD_SETBITS) {
+ bv_sda = rq->wIndex.bytes[0];
+ bv_scl = rq->wIndex.bytes[1];
+ return 0;
+ }
+ if (rq->bRequest == USBCMD_START) {
+ DDRB &= ~(bv_sda | bv_scl);
+ _delay_us(1000);
+ DDRB |= bv_sda;
+ _delay_us(1000);
+ DDRB |= bv_scl;
+ return 0;
+ }
+ if (rq->bRequest == USBCMD_STOP) {
+ DDRB &= ~bv_scl;
+ _delay_us(100);
+ DDRB &= ~bv_sda;
+ _delay_us(100);
+ return 0;
+ }
+ if (rq->bRequest == USBCMD_TX) {
+ buf = rq->wIndex.bytes[0]; // byte to transmit
+ for (i = 0; i <= 8; i++) {
+ if ((buf & 0x80) || (i == 8)) {
+ DDRB &= ~bv_sda;
+ } else {
+ DDRB |= bv_sda;
+ }
+ buf <<= 1;
+ _delay_us(100);
+ DDRB &= ~bv_scl;
+ _delay_us(100);
+ if (i == 8) {
+ if (PINB & bv_sda) {
+ replyBuf[0] = 0;
+ } else {
+ replyBuf[0] = 1;
+ }
+ }
+ DDRB |= bv_scl;
+ _delay_us(100);
+ }
+ return 1;
+ }
+ if (rq->bRequest == USBCMD_RX) {
+ buf = rq->wIndex.bytes[0]; // true <=> transmit ack
+ DDRB &= ~bv_sda;
+ replyBuf[0] = 0;
+ for (i = 0; i <= 8; i++) {
+ if ((i == 8) && buf) {
+ DDRB |= bv_sda;
+ }
+ DDRB &= ~bv_scl;
+ _delay_us(100);
+ if ((i < 8) && ( PINB & bv_sda)) {
+ replyBuf[0] |= _BV(7-i);
+ }
+ else if ((i == 8) && buf) {
+ DDRB &= ~bv_sda;
+ }
+ DDRB |= bv_scl;
+ _delay_us(100);
+ }
+ return 1;
+ }
+ return 0;
}
/* allow some inter-device compatibility */
diff --git a/global_config.h b/global_config.h
index 1a4e8b5..7fcd122 100644
--- a/global_config.h
+++ b/global_config.h
@@ -1,6 +1,11 @@
#define USBDEV_VERSION_MAJOR 0
-#define USBDEV_VERSION_MINOR 1
+#define USBDEV_VERSION_MINOR 2
#define USBCMD_ECHO 0
#define USBCMD_GETPORT 1
#define USBCMD_SETPORT 2
+#define USBCMD_SETBITS 3
+#define USBCMD_START 4
+#define USBCMD_STOP 5
+#define USBCMD_TX 6
+#define USBCMD_RX 7