1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/spi.c Mon Feb 11 16:48:30 2013 +0000
1.3 @@ -0,0 +1,310 @@
1.4 +/*
1.5 + * Ben NanoNote and Arduino USB Host shield communication.
1.6 + *
1.7 + * Copyright 2013 Paul Boddie
1.8 + *
1.9 + * SPI functions derived from those in lib/atben.c by Werner Almesberger:
1.10 + *
1.11 + * Copyright 2010-2011 Werner Almesberger
1.12 + *
1.13 + * This program is free software; you can redistribute it and/or modify
1.14 + * it under the terms of the GNU General Public License as published by
1.15 + * the Free Software Foundation; either version 2 of the License, or
1.16 + * (at your option) any later version.
1.17 + */
1.18 +
1.19 +#include <ubb/ubb.h>
1.20 +#include <stdio.h>
1.21 +#include <time.h>
1.22 +#include <unistd.h>
1.23 +
1.24 +/* Pin assignments:
1.25 + *
1.26 + * Sniffer UBB Shield
1.27 + * ------- ---- ------
1.28 + * DAT2 DAT2 9 (INT)
1.29 + * CD DAT3 10 (SS)
1.30 + * CMD CMD 7 (RESET)
1.31 + * VCC VDD VIN
1.32 + * CLK CLK 13 (SCLK)
1.33 + * GND GND GND
1.34 + * DAT0 DAT0 11 (MOSI)
1.35 + * DAT1 DAT1 12 (MISO)
1.36 + * 8 (GPX) (not assigned)
1.37 + */
1.38 +
1.39 +#define MAX_RESET UBB_CMD
1.40 +#define MAX_SCLK UBB_CLK
1.41 +#define MAX_MOSI UBB_DAT0
1.42 +#define MAX_MISO UBB_DAT1
1.43 +#define MAX_INT UBB_DAT2
1.44 +#define MAX_SS UBB_DAT3
1.45 +
1.46 +/* MAX3421E definitions. */
1.47 +
1.48 +#define MAX_REG_READ 0x00
1.49 +#define MAX_REG_WRITE 0x02
1.50 +
1.51 +#define MAX_REG_USBIRQ 13
1.52 +#define MAX_REG_USBIEN 14
1.53 +#define MAX_REG_USBCTL 15
1.54 +#define MAX_REG_CPUCTL 16
1.55 +#define MAX_REG_PINCTL 17
1.56 +#define MAX_REG_REVISION 18
1.57 +#define MAX_REG_GPINPOL 24
1.58 +#define MAX_REG_HIRQ 25
1.59 +#define MAX_REG_HIEN 26
1.60 +#define MAX_REG_MODE 27
1.61 +#define MAX_REG_HCTL 29
1.62 +#define MAX_REG_HRSL 31
1.63 +
1.64 +#define MAX_USBIRQ_OSCOKIRQ 1
1.65 +#define MAX_USBIRQ_NOVBUSIRQ 32
1.66 +#define MAX_USBIRQ_VBUSIRQ 64
1.67 +
1.68 +#define MAX_USBCTL_PWRDOWN 16
1.69 +#define MAX_USBCTL_CHIPRES 32
1.70 +
1.71 +#define MAX_CPUCTL_IE 1
1.72 +
1.73 +#define MAX_PINCTL_POSINT_LOW 0
1.74 +#define MAX_PINCTL_POSINT_HIGH 4
1.75 +#define MAX_PINCTL_INTLEVEL_EDGE 0
1.76 +#define MAX_PINCTL_INTLEVEL_LEVEL 8
1.77 +#define MAX_PINCTL_FDUPSPI_HALF 0
1.78 +#define MAX_PINCTL_FDUPSPI_FULL 16
1.79 +
1.80 +#define MAX_HIRQ_BUSEVENTIRQ 1
1.81 +#define MAX_HIRQ_RWUIRQ 2
1.82 +#define MAX_HIRQ_RCVDAVIRQ 4
1.83 +#define MAX_HIRQ_SNDBAVIRQ 8
1.84 +#define MAX_HIRQ_SUSDNIRQ 16
1.85 +#define MAX_HIRQ_CONDETIRQ 32
1.86 +#define MAX_HIRQ_FRAMEIRQ 64
1.87 +#define MAX_HIRQ_HXFRDNIRQ 128
1.88 +
1.89 +#define MAX_HIEN_CONDETIE 32
1.90 +
1.91 +#define MAX_MODE_PERIPHERAL 0
1.92 +#define MAX_MODE_HOST 1
1.93 +#define MAX_MODE_LOWSPEED 2
1.94 +#define MAX_MODE_SOFKAENAB 8
1.95 +#define MAX_MODE_SEPIRQ_OFF 0
1.96 +#define MAX_MODE_SEPIRQ_ON 16
1.97 +#define MAX_MODE_DMPULLDN 64
1.98 +#define MAX_MODE_DPPULLDN 128
1.99 +
1.100 +#define MAX_HCTL_SAMPLEBUS 4
1.101 +
1.102 +#define MAX_HRSL_JSTATUS 128
1.103 +#define MAX_HRSL_KSTATUS 64
1.104 +
1.105 +#define max_reg(n) ((uint8_t) (n << 3))
1.106 +#define max_reg_read(n) (max_reg(n) | MAX_REG_READ)
1.107 +#define max_reg_write(n) (max_reg(n) | MAX_REG_WRITE)
1.108 +
1.109 +#define nanosleep(a, b) if (0)
1.110 +#define usleep(a) if (0)
1.111 +
1.112 +struct timespec tCSS = {0, 20},
1.113 + tL = {0, 30},
1.114 + tCSW = {0, 200},
1.115 + tCL = {0, 17},
1.116 + tCH = {0, 17},
1.117 + tDS = {0, 5},
1.118 + tDH = {0, 10},
1.119 + tDO = {0, 15},
1.120 + tDI = {0, 15},
1.121 + tON = {0, 4},
1.122 + tRESET = {0, 200},
1.123 + tTEST = {0, 100};
1.124 +
1.125 +void spi_begin()
1.126 +{
1.127 + CLR(MAX_SS);
1.128 + nanosleep(&tL, NULL); /* tCSS is the minimum, but tL is more conservative */
1.129 +}
1.130 +
1.131 +void spi_end()
1.132 +{
1.133 + SET(MAX_SS);
1.134 + nanosleep(&tCSW, NULL);
1.135 +}
1.136 +
1.137 +/**
1.138 + * Send the given value via MOSI while receiving a value via MISO.
1.139 + * This requires full-duplex SPI and will produce a status value for the first
1.140 + * value sent (the command).
1.141 + */
1.142 +uint8_t spi_sendrecv(uint8_t v)
1.143 +{
1.144 + uint8_t result = 0;
1.145 + uint8_t mask;
1.146 +
1.147 + for (mask = 0x80; mask; mask >>= 1)
1.148 + {
1.149 + if (v & mask)
1.150 + {
1.151 + #ifdef DEBUG
1.152 + printf("1");
1.153 + #endif
1.154 + SET(MAX_MOSI);
1.155 + }
1.156 + else
1.157 + {
1.158 + #ifdef DEBUG
1.159 + printf("0");
1.160 + #endif
1.161 + CLR(MAX_MOSI);
1.162 + }
1.163 +
1.164 + /* Wait for stable output signal. */
1.165 +
1.166 + nanosleep(&tDS, NULL);
1.167 +
1.168 + SET(MAX_SCLK);
1.169 +
1.170 + if (PIN(MAX_MISO))
1.171 + result |= mask;
1.172 +
1.173 + nanosleep(&tCH, NULL);
1.174 + CLR(MAX_SCLK);
1.175 + nanosleep(&tCL, NULL);
1.176 + }
1.177 +
1.178 + #ifdef DEBUG
1.179 + printf("\n");
1.180 + #endif
1.181 + return result;
1.182 +}
1.183 +
1.184 +uint8_t max_read(uint8_t reg, uint8_t *status)
1.185 +{
1.186 + uint8_t result = 0, tmpstatus = 0;
1.187 +
1.188 + tmpstatus = 0;
1.189 +
1.190 + spi_begin();
1.191 + tmpstatus = spi_sendrecv(max_reg_read(reg));
1.192 + result = spi_sendrecv(0);
1.193 + spi_end();
1.194 +
1.195 + if (status != NULL)
1.196 + *status = tmpstatus;
1.197 +
1.198 + return result;
1.199 +}
1.200 +
1.201 +uint8_t max_write(uint8_t reg, uint8_t value)
1.202 +{
1.203 + uint8_t status = 0;
1.204 +
1.205 + spi_begin();
1.206 + status = spi_sendrecv(max_reg_write(reg));
1.207 + spi_sendrecv(value);
1.208 + spi_end();
1.209 +
1.210 + return status;
1.211 +}
1.212 +
1.213 +void chipreset()
1.214 +{
1.215 + printf("Resetting...\n");
1.216 + max_write(MAX_REG_USBCTL, MAX_USBCTL_CHIPRES);
1.217 +
1.218 + printf("Clearing the reset...\n");
1.219 + max_write(MAX_REG_USBCTL, 0);
1.220 +}
1.221 +
1.222 +uint8_t check()
1.223 +{
1.224 + uint8_t oscillator;
1.225 +
1.226 + oscillator = max_read(MAX_REG_USBIRQ, NULL);
1.227 +
1.228 + return (oscillator & ~(MAX_USBIRQ_NOVBUSIRQ | MAX_USBIRQ_VBUSIRQ)) == MAX_USBIRQ_OSCOKIRQ;
1.229 +}
1.230 +
1.231 +uint8_t wait()
1.232 +{
1.233 + uint16_t timeout = 1024;
1.234 +
1.235 + /* Wait for the oscillator before performing USB activity. */
1.236 +
1.237 + printf("Waiting...\n");
1.238 +
1.239 + while ((timeout > 0) && (!check()))
1.240 + {
1.241 + usleep(3000); /* 3ms */
1.242 + timeout--;
1.243 + }
1.244 +
1.245 + printf("Iterations remaining: %d\n", timeout);
1.246 +
1.247 + return timeout;
1.248 +}
1.249 +
1.250 +int main(int argc, char *argv[])
1.251 +{
1.252 + uint8_t status = 0, revision = 0, result = 0;
1.253 + uint16_t count;
1.254 +
1.255 + if (ubb_open(0) < 0) {
1.256 + perror("ubb_open");
1.257 + return 1;
1.258 + }
1.259 +
1.260 + ubb_power(1);
1.261 + printf("Power on.\n");
1.262 +
1.263 + OUT(MAX_SS);
1.264 + OUT(MAX_MOSI);
1.265 + OUT(MAX_SCLK);
1.266 + OUT(MAX_RESET);
1.267 + IN(MAX_INT);
1.268 + IN(MAX_MISO);
1.269 +
1.270 + /* Initialise SPI. */
1.271 + /* Set SS# to 1. */
1.272 +
1.273 + SET(MAX_SS);
1.274 + CLR(MAX_MOSI);
1.275 + CLR(MAX_SCLK);
1.276 + SET(MAX_RESET);
1.277 +
1.278 + /* Initialise the MAX3421E. */
1.279 +
1.280 + /* Set full-duplex, interrupt signalling. */
1.281 +
1.282 + printf("Setting pin control...\n");
1.283 + max_write(MAX_REG_PINCTL, MAX_PINCTL_INTLEVEL_LEVEL | MAX_PINCTL_FDUPSPI_FULL);
1.284 +
1.285 + chipreset();
1.286 + printf("Ready? %d\n", wait());
1.287 +
1.288 + /* Read from the REVISION register. */
1.289 +
1.290 + printf("Reading...\n");
1.291 + revision = max_read(MAX_REG_REVISION, &status);
1.292 + printf("Status = %x\n", status);
1.293 + printf("Revision = %x\n", revision);
1.294 +
1.295 + /* Check various registers. */
1.296 +
1.297 + for (count = 0; count < 256; count++)
1.298 + {
1.299 + max_write(MAX_REG_GPINPOL, count);
1.300 + result = max_read(MAX_REG_GPINPOL, NULL);
1.301 + if (count != result)
1.302 + {
1.303 + printf("Count: %d\n", count);
1.304 + printf("Retrieved: %d\n", result);
1.305 + printf("Status = %x\n", status);
1.306 + }
1.307 + }
1.308 +
1.309 + printf("Closing...\n");
1.310 + ubb_close(0);
1.311 +
1.312 + return 0;
1.313 +}
2.1 --- a/test.c Sun Feb 10 20:18:28 2013 +0000
2.2 +++ b/test.c Mon Feb 11 16:48:30 2013 +0000
2.3 @@ -46,10 +46,15 @@
2.4 #define MAX_REG_WRITE 0x02
2.5
2.6 #define MAX_REG_USBIRQ 13
2.7 +#define MAX_REG_USBIEN 14
2.8 #define MAX_REG_USBCTL 15
2.9 +#define MAX_REG_CPUCTL 16
2.10 #define MAX_REG_PINCTL 17
2.11 #define MAX_REG_REVISION 18
2.12 +#define MAX_REG_HIRQ 25
2.13 +#define MAX_REG_HIEN 26
2.14 #define MAX_REG_MODE 27
2.15 +#define MAX_REG_HCTL 29
2.16 #define MAX_REG_HRSL 31
2.17
2.18 #define MAX_USBIRQ_OSCOKIRQ 1
2.19 @@ -59,6 +64,8 @@
2.20 #define MAX_USBCTL_PWRDOWN 16
2.21 #define MAX_USBCTL_CHIPRES 32
2.22
2.23 +#define MAX_CPUCTL_IE 1
2.24 +
2.25 #define MAX_PINCTL_POSINT_LOW 0
2.26 #define MAX_PINCTL_POSINT_HIGH 4
2.27 #define MAX_PINCTL_INTLEVEL_EDGE 0
2.28 @@ -66,17 +73,38 @@
2.29 #define MAX_PINCTL_FDUPSPI_HALF 0
2.30 #define MAX_PINCTL_FDUPSPI_FULL 16
2.31
2.32 +#define MAX_HIRQ_BUSEVENTIRQ 1
2.33 +#define MAX_HIRQ_RWUIRQ 2
2.34 +#define MAX_HIRQ_RCVDAVIRQ 4
2.35 +#define MAX_HIRQ_SNDBAVIRQ 8
2.36 +#define MAX_HIRQ_SUSDNIRQ 16
2.37 +#define MAX_HIRQ_CONDETIRQ 32
2.38 +#define MAX_HIRQ_FRAMEIRQ 64
2.39 +#define MAX_HIRQ_HXFRDNIRQ 128
2.40 +
2.41 +#define MAX_HIEN_CONDETIE 32
2.42 +
2.43 #define MAX_MODE_PERIPHERAL 0
2.44 #define MAX_MODE_HOST 1
2.45 +#define MAX_MODE_LOWSPEED 2
2.46 +#define MAX_MODE_SOFKAENAB 8
2.47 #define MAX_MODE_SEPIRQ_OFF 0
2.48 #define MAX_MODE_SEPIRQ_ON 16
2.49 #define MAX_MODE_DMPULLDN 64
2.50 #define MAX_MODE_DPPULLDN 128
2.51
2.52 +#define MAX_HCTL_SAMPLEBUS 4
2.53 +
2.54 +#define MAX_HRSL_JSTATUS 128
2.55 +#define MAX_HRSL_KSTATUS 64
2.56 +
2.57 #define max_reg(n) ((uint8_t) (n << 3))
2.58 #define max_reg_read(n) (max_reg(n) | MAX_REG_READ)
2.59 #define max_reg_write(n) (max_reg(n) | MAX_REG_WRITE)
2.60
2.61 +#define nanosleep(a, b) if (0)
2.62 +#define usleep(a) if (0)
2.63 +
2.64 struct timespec tCSS = {0, 20},
2.65 tL = {0, 30},
2.66 tCSW = {0, 200},
2.67 @@ -116,12 +144,16 @@
2.68 {
2.69 if (v & mask)
2.70 {
2.71 + #ifdef DEBUG
2.72 printf("1");
2.73 + #endif
2.74 SET(MAX_MOSI);
2.75 }
2.76 else
2.77 {
2.78 + #ifdef DEBUG
2.79 printf("0");
2.80 + #endif
2.81 CLR(MAX_MOSI);
2.82 }
2.83
2.84 @@ -139,7 +171,9 @@
2.85 nanosleep(&tCL, NULL);
2.86 }
2.87
2.88 + #ifdef DEBUG
2.89 printf("\n");
2.90 + #endif
2.91 return result;
2.92 }
2.93
2.94 @@ -172,13 +206,6 @@
2.95 return status;
2.96 }
2.97
2.98 -void reset()
2.99 -{
2.100 - SET(MAX_RESET);
2.101 - nanosleep(&tRESET, NULL);
2.102 - CLR(MAX_RESET);
2.103 -}
2.104 -
2.105 void chipreset()
2.106 {
2.107 printf("Resetting...\n");
2.108 @@ -197,9 +224,38 @@
2.109 return (oscillator & ~(MAX_USBIRQ_NOVBUSIRQ | MAX_USBIRQ_VBUSIRQ)) == MAX_USBIRQ_OSCOKIRQ;
2.110 }
2.111
2.112 +uint8_t wait()
2.113 +{
2.114 + uint16_t timeout = 1024;
2.115 +
2.116 + /* Wait for the oscillator before performing USB activity. */
2.117 +
2.118 + printf("Waiting...\n");
2.119 +
2.120 + while ((timeout > 0) && (!check()))
2.121 + {
2.122 + usleep(3000); /* 3ms */
2.123 + timeout--;
2.124 + }
2.125 +
2.126 + printf("Iterations remaining: %d\n", timeout);
2.127 +
2.128 + return timeout;
2.129 +}
2.130 +
2.131 +uint8_t samplebus()
2.132 +{
2.133 + uint8_t result;
2.134 +
2.135 + result = max_read(MAX_REG_HCTL, NULL);
2.136 +
2.137 + return !(result & MAX_HCTL_SAMPLEBUS);
2.138 +}
2.139 +
2.140 int main(int argc, char *argv[])
2.141 {
2.142 uint8_t status = 0, revision = 0, hrsl = 0;
2.143 + uint16_t count;
2.144
2.145 if (ubb_open(0) < 0) {
2.146 perror("ubb_open");
2.147 @@ -217,12 +273,12 @@
2.148 IN(MAX_MISO);
2.149
2.150 /* Initialise SPI. */
2.151 - /* Set SS to 1 (or SS~ to 0). */
2.152 + /* Set SS# to 1. */
2.153
2.154 SET(MAX_SS);
2.155 CLR(MAX_MOSI);
2.156 CLR(MAX_SCLK);
2.157 - CLR(MAX_RESET);
2.158 + SET(MAX_RESET);
2.159
2.160 /* Initialise the MAX3421E. */
2.161
2.162 @@ -231,16 +287,37 @@
2.163 printf("Setting pin control...\n");
2.164 max_write(MAX_REG_PINCTL, MAX_PINCTL_INTLEVEL_LEVEL | MAX_PINCTL_FDUPSPI_FULL);
2.165
2.166 - reset();
2.167 chipreset();
2.168 - printf("Ready? %d\n", check());
2.169 + printf("Ready? %d\n", wait());
2.170 +
2.171 + /* Check various registers. */
2.172 +
2.173 + printf("Mode: %x\n", max_read(MAX_REG_MODE, &status));
2.174 + printf("IRQ: %x\n", max_read(MAX_REG_HIRQ, &status));
2.175
2.176 /* Set host mode. */
2.177
2.178 printf("Setting mode...\n");
2.179 status = max_write(MAX_REG_MODE, MAX_MODE_HOST | MAX_MODE_SEPIRQ_OFF | MAX_MODE_DMPULLDN | MAX_MODE_DPPULLDN);
2.180 printf("Status = %x\n", status);
2.181 - printf("Ready? %d\n", check());
2.182 +
2.183 + printf("Setting INT signalling...\n");
2.184 + status = max_write(MAX_REG_CPUCTL, MAX_CPUCTL_IE);
2.185 + printf("Status = %x\n", status);
2.186 +
2.187 + printf("Setting connection signalling...\n");
2.188 + status = max_write(MAX_REG_HIEN, MAX_HIEN_CONDETIE);
2.189 + printf("Status = %x\n", status);
2.190 +
2.191 + /* Check various registers. */
2.192 +
2.193 + printf("Mode: %x\n", max_read(MAX_REG_MODE, &status));
2.194 + printf("IRQ: %x\n", max_read(MAX_REG_HIRQ, &status));
2.195 + printf("IE: %x\n", max_read(MAX_REG_HIEN, &status));
2.196 + printf("CPU: %x\n", max_read(MAX_REG_CPUCTL, &status));
2.197 + printf("Pin: %x\n", max_read(MAX_REG_PINCTL, &status));
2.198 + printf("USBIRQ: %x\n", max_read(MAX_REG_USBIRQ, &status));
2.199 + printf("USBIE: %x\n", max_read(MAX_REG_USBIEN, &status));
2.200
2.201 /* Read from the REVISION register. */
2.202
2.203 @@ -248,13 +325,26 @@
2.204 revision = max_read(MAX_REG_REVISION, &status);
2.205 printf("Status = %x\n", status);
2.206 printf("Revision = %x\n", revision);
2.207 - printf("Ready? %d\n", check());
2.208 +
2.209 + for (count = 0; count < 10; count++)
2.210 + {
2.211 + printf("INT? %d\n", PIN(MAX_INT));
2.212 + printf("Status = %x\n", status);
2.213
2.214 - printf("HRSL...\n");
2.215 - hrsl = max_read(MAX_REG_HRSL, &status);
2.216 - printf("Status = %x\n", status);
2.217 - printf("HRSL = %x\n", hrsl);
2.218 - printf("Ready? %d\n", check());
2.219 + if (PIN(MAX_INT))
2.220 + {
2.221 + if (status & (MAX_HIRQ_SUSDNIRQ | MAX_HIRQ_CONDETIRQ))
2.222 + {
2.223 + printf("HRSL...\n");
2.224 + hrsl = max_read(MAX_REG_HRSL, &status);
2.225 + printf("Status = %x\n", status);
2.226 + printf("HRSL = %x\n", hrsl);
2.227 + }
2.228 +
2.229 + printf("Clearing status...\n");
2.230 + max_write(MAX_REG_HIRQ, status & (MAX_HIRQ_SUSDNIRQ | MAX_HIRQ_SNDBAVIRQ | MAX_HIRQ_BUSEVENTIRQ));
2.231 + }
2.232 + }
2.233
2.234 printf("Closing...\n");
2.235 ubb_close(0);