# HG changeset patch # User Paul Boddie # Date 1360363808 0 # Node ID 5f9455ebcd32722a35f0e1b98a245d3b96559ac2 Test programs for the USB Host Shield (test.c) and the M74HC595B1R shift register (shift.c). diff -r 000000000000 -r 5f9455ebcd32 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Fri Feb 08 22:50:08 2013 +0000 @@ -0,0 +1,37 @@ +# Makefile - Build the UBB library +# +# Copyright 2013 Paul Boddie +# +# 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. + +LIBUBB = ../ben-blinkenlights/libubb +SYSLIBS = ../openwrt-xburst/staging_dir/target-mipsel_eglibc-2.15/usr/lib + +ARCH = mipsel-openwrt-linux +CC = $(ARCH)-gcc + +CFLAGS = -g -Wall -fPIC -march=mips32 -I$(LIBUBB)/include +LDFLAGS = -lubb -L$(LIBUBB) #-static #-L$(SYSLIBS) + +TARGET = test +SRC = test.c +OBJ = $(SRC:.c=.o) + +.PHONY: all clean distclean + +all: $(TARGET) + +clean: + rm -f $(OBJ) $(TARGET) + +distclean: clean + echo "Nothing else to clean." + +$(TARGET): $(OBJ) + $(CC) $(LDFLAGS) $< -o $@ + +.c.o: + $(CC) -c $(CFLAGS) $< -o $@ diff -r 000000000000 -r 5f9455ebcd32 shift.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shift.c Fri Feb 08 22:50:08 2013 +0000 @@ -0,0 +1,124 @@ +#include +#include +#include + +/* Pin assignments: + * + * M74HC595B1R + * + * QB |----| VCC UBB_VDD + * QC | | QA + * QD | | SI UBB_DAT2 + * QE | | G UBB_DAT0 + * QF | | RCK UBB_DAT1 + * QG | | SCK UBB_CLK + * QH | | SCLR UBB_CMD + * UBB_GND GND |----| QH' UBB_DAT3 + */ + +#define SHIFT_SI UBB_DAT2 +#define SHIFT_QH UBB_DAT3 +#define SHIFT_SCLR UBB_CMD +#define SHIFT_SCK UBB_CLK +#define SHIFT_G UBB_DAT0 +#define SHIFT_RCK UBB_DAT1 + +struct timespec tSCKs = {0, 15}, + tWH = {0, 15}, + tWL = {0, 15}; + +void shift_in(uint8_t v) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) + { + if (v & mask) + { + printf("1"); + SET(SHIFT_SI); + } + else + { + printf("0"); + CLR(SHIFT_SI); + } + + nanosleep(&tSCKs, NULL); + SET(SHIFT_SCK); + nanosleep(&tWH, NULL); + CLR(SHIFT_SCK); + } + + printf("\n"); +} + +uint8_t shift_out() +{ + uint8_t mask, result = 0; + + for (mask = 0x80; mask; mask >>= 1) + { + if (PIN(SHIFT_QH)) + { + result |= mask; + printf("1"); + } + else + printf("0"); + + nanosleep(&tSCKs, NULL); + SET(SHIFT_SCK); + nanosleep(&tWH, NULL); + CLR(SHIFT_SCK); + } + + printf("\n"); + return result; +} + +int main(int argc, char *argv[]) +{ + uint8_t result = 0; + + if (ubb_open(0) < 0) { + perror("ubb_open"); + return 1; + } + + ubb_power(1); + printf("Power on.\n"); + + OUT(SHIFT_SI); + OUT(SHIFT_RCK); + OUT(SHIFT_SCLR); + OUT(SHIFT_SCK); + OUT(SHIFT_G); + IN(SHIFT_QH); + + CLR(SHIFT_SCK); + CLR(SHIFT_RCK); + + /* Clear the register. */ + + CLR(SHIFT_SCLR); + SET(SHIFT_SCK); + nanosleep(&tWL, NULL); + CLR(SHIFT_SCK); + SET(SHIFT_SCLR); + + /* Shift in a value. */ + + shift_in(0xa6); + + /* Shift out the value. */ + + result = shift_out(); + + printf("Result: %x\n", result); + + printf("Closing...\n"); + ubb_close(0); + + return 0; +} diff -r 000000000000 -r 5f9455ebcd32 test.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test.c Fri Feb 08 22:50:08 2013 +0000 @@ -0,0 +1,286 @@ +/* + * Ben NanoNote and Arduino USB Host shield communication. + * + * Copyright 2013 Paul Boddie + * + * SPI functions derived from those in lib/atben.c by Werner Almesberger: + * + * Copyright 2010-2011 Werner Almesberger + * + * 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. + */ + +#include +#include +#include + +/* Pin assignments: + * + * Sniffer UBB Shield + * ------- ---- ------ + * DAT2 DAT2 9 (INT) + * CD DAT3 10 (SS) + * CMD CMD 7 (RESET) + * VCC VDD VIN + * CLK CLK 13 (SCLK) + * GND GND GND + * DAT0 DAT0 11 (MOSI) + * DAT1 DAT1 12 (MISO) + * 8 (GPX) (not assigned) + */ + +#define MAX_RESET UBB_CMD +#define MAX_SCLK UBB_CLK +#define MAX_MOSI UBB_DAT0 +#define MAX_MISO UBB_DAT1 +#define MAX_INT UBB_DAT2 +#define MAX_SS UBB_DAT3 + +/* MAX3421E definitions. */ + +#define MAX_REG_READ 0x00 +#define MAX_REG_WRITE 0x02 + +#define MAX_REG_USBCTL 15 +#define MAX_REG_PINCTL 17 +#define MAX_REG_REVISION 18 +#define MAX_REG_MODE 27 +#define MAX_REG_HRSL 31 + +#define MAX_USBCTL_PWRDOWN 16 +#define MAX_USBCTL_CHIPRES 32 + +#define MAX_PINCTL_POSINT_LOW 0 +#define MAX_PINCTL_POSINT_HIGH 4 +#define MAX_PINCTL_INTLEVEL_EDGE 0 +#define MAX_PINCTL_INTLEVEL_LEVEL 8 +#define MAX_PINCTL_FDUPSPI_HALF 0 +#define MAX_PINCTL_FDUPSPI_FULL 16 + +#define MAX_MODE_PERIPHERAL 0 +#define MAX_MODE_HOST 1 +#define MAX_MODE_SEPIRQ_OFF 0 +#define MAX_MODE_SEPIRQ_ON 16 +#define MAX_MODE_DMPULLDN 64 +#define MAX_MODE_DPPULLDN 128 + +#define max_reg(n) ((uint8_t) (n << 3)) +#define max_reg_read(n) (max_reg(n) | MAX_REG_READ) +#define max_reg_write(n) (max_reg(n) | MAX_REG_WRITE) + +struct timespec tCSS = {0, 20}, + tL = {0, 30}, + tCSW = {0, 200}, + tCL = {0, 17}, + tCH = {0, 17}, + tDS = {0, 5}, + tDH = {0, 10}, + tDO = {0, 15}, + tDI = {0, 15}, + tON = {0, 4}, + tRESET = {0, 200}, + tTEST = {0, 100}; + +void spi_begin() +{ + CLR(MAX_SS); + nanosleep(&tL, NULL); /* tCSS is the minimum, but tL is more conservative */ +} + +void spi_end() +{ + SET(MAX_SS); + nanosleep(&tCSW, NULL); +} + +/** + * Send the given value via MOSI while receiving a value via MISO. + * This requires full-duplex SPI and will produce a status value for the first + * value sent (the command). + */ +uint8_t spi_sendrecv(uint8_t v) +{ + uint8_t result = 0; + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) + { + if (v & mask) + { + printf("1"); + SET(MAX_MOSI); + } + else + { + printf("0"); + CLR(MAX_MOSI); + } + + /* Wait for stable output signal. */ + + nanosleep(&tDS, NULL); + + SET(MAX_SCLK); + + if (PIN(MAX_MISO)) + result |= mask; + + nanosleep(&tCH, NULL); + CLR(MAX_SCLK); + nanosleep(&tCL, NULL); + } + + printf("\n"); + return result; +} + +void spi_send(uint8_t v) +{ + uint8_t mask; + + OUT(MAX_MOSI); + + for (mask = 0x80; mask; mask >>= 1) + { + if (v & mask) + { + printf("1"); + SET(MAX_MOSI); + } + else + { + printf("0"); + CLR(MAX_MOSI); + } + + nanosleep(&tDS, NULL); + + SET(MAX_SCLK); + nanosleep(&tCH, NULL); + CLR(MAX_SCLK); + nanosleep(&tDO, NULL); + } + + printf("\n"); +} + +uint8_t spi_recv() +{ + uint8_t mask, result = 0; + + IN(MAX_MOSI); + + for (mask = 0x80; mask; mask >>= 1) + { + nanosleep(&tON, NULL); + + SET(MAX_SCLK); + + if (PIN(MAX_MOSI)) + { + printf("1"); + result |= mask; + } + else + printf("0"); + + nanosleep(&tCH, NULL); + CLR(MAX_SCLK); + nanosleep(&tDO, NULL); + } + + printf("\n"); + return result; +} + +int main(int argc, char *argv[]) +{ + uint8_t status = 0, revision = 0, hrsl = 0; + + if (ubb_open(0) < 0) { + perror("ubb_open"); + return 1; + } + + ubb_power(1); + printf("Power on.\n"); + + OUT(MAX_SS); + OUT(MAX_MOSI); + OUT(MAX_SCLK); + OUT(MAX_RESET); + IN(MAX_INT); + IN(MAX_MISO); + + /* Initialise SPI. */ + /* Set SS to 1 (or SS~ to 0). */ + + SET(MAX_SS); + CLR(MAX_MOSI); + CLR(MAX_SCLK); + CLR(MAX_RESET); + + /* Initialise the MAX3421E. */ + + /* Set full-duplex, interrupt signalling. */ + + printf("Setting pin control...\n"); + spi_begin(); + spi_sendrecv(max_reg_write(MAX_REG_PINCTL)); + spi_sendrecv(MAX_PINCTL_INTLEVEL_LEVEL | MAX_PINCTL_FDUPSPI_FULL); + spi_end(); + printf("INT set to %d\n", PIN(MAX_INT)); + + SET(MAX_RESET); + nanosleep(&tRESET, NULL); + CLR(MAX_RESET); + + printf("Resetting...\n"); + spi_begin(); + spi_sendrecv(max_reg_write(MAX_REG_USBCTL)); + spi_sendrecv(MAX_USBCTL_CHIPRES); + spi_end(); + + printf("Clearing the reset...\n"); + spi_begin(); + spi_sendrecv(max_reg_write(MAX_REG_USBCTL)); + spi_sendrecv(0); + spi_end(); + + /* Set host mode. */ + + printf("Setting mode...\n"); + spi_begin(); + spi_sendrecv(max_reg_write(MAX_REG_MODE)); + spi_sendrecv(MAX_MODE_HOST | MAX_MODE_SEPIRQ_OFF | MAX_MODE_DMPULLDN | MAX_MODE_DPPULLDN); + spi_end(); + printf("INT set to %d\n", PIN(MAX_INT)); + + /* Read from the REVISION register. */ + + printf("Reading...\n"); + spi_begin(); + status = spi_sendrecv(max_reg_read(MAX_REG_REVISION)); + revision = spi_sendrecv(0); + spi_end(); + printf("Status = %x\n", status); + printf("Revision = %x\n", revision); + printf("INT set to %d\n", PIN(MAX_INT)); + + printf("HRSL...\n"); + spi_begin(); + status = spi_sendrecv(max_reg_read(MAX_REG_HRSL)); + hrsl = spi_sendrecv(0); + spi_end(); + printf("Status = %x\n", status); + printf("HRSL = %x\n", hrsl); + printf("INT set to %d\n", PIN(MAX_INT)); + + printf("Closing...\n"); + ubb_close(0); + + return 0; +}