From 554d78c9c73731705ab536e009ef47760dd2df3f Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sat, 9 Jan 2016 21:58:53 +0100 Subject: move software I2C implementation to ATTiny --- commandline/i2c-util.c | 70 ++++++++++++++++++++++++++++++++++ commandline/i2c-util.h | 7 ++++ commandline/i2cdetect.c | 6 +-- commandline/i2cget.c | 22 +++++------ commandline/i2cset.c | 14 +++---- firmware/main.c | 99 +++++++++++++++++++++++++++++++++++++++++-------- global_config.h | 7 +++- 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 -- cgit v1.2.3