1 /* 2 * Ben NanoNote and Arduino USB Host shield communication. 3 * 4 * Copyright 2013 Paul Boddie 5 * 6 * SPI functions derived from those in lib/atben.c by Werner Almesberger: 7 * 8 * Copyright 2010-2011 Werner Almesberger 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 */ 15 16 #include <ubb/ubb.h> 17 #include <stdio.h> 18 #include <time.h> 19 #include <unistd.h> 20 #include <signal.h> 21 #include <stdlib.h> 22 23 /* Pin assignments: 24 * 25 * Sniffer UBB Shield 26 * ------- ---- ------ 27 * DAT2 DAT2 9 (INT) 28 * CD DAT3 10 (SS) 29 * CMD CMD 7 (RESET) 30 * VCC VDD VIN 31 * CLK CLK 13 (SCLK) 32 * GND GND GND 33 * DAT0 DAT0 11 (MOSI) 34 * DAT1 DAT1 12 (MISO) 35 * 8 (GPX) (not assigned) 36 */ 37 38 #define MAX_RESET UBB_CMD 39 #define MAX_SCLK UBB_CLK 40 #define MAX_MOSI UBB_DAT0 41 #define MAX_MISO UBB_DAT1 42 #define MAX_INT UBB_DAT2 43 #define MAX_SS UBB_DAT3 44 45 /* MAX3421E definitions. */ 46 47 #define MAX_REG_READ 0x00 48 #define MAX_REG_WRITE 0x02 49 50 #define MAX_REG_USBIRQ 13 51 #define MAX_REG_USBIEN 14 52 #define MAX_REG_USBCTL 15 53 #define MAX_REG_CPUCTL 16 54 #define MAX_REG_PINCTL 17 55 #define MAX_REG_REVISION 18 56 #define MAX_REG_HIRQ 25 57 #define MAX_REG_HIEN 26 58 #define MAX_REG_MODE 27 59 #define MAX_REG_HCTL 29 60 #define MAX_REG_HRSL 31 61 62 #define MAX_USBIRQ_OSCOKIRQ 1 63 #define MAX_USBIRQ_NOVBUSIRQ 32 64 #define MAX_USBIRQ_VBUSIRQ 64 65 66 #define MAX_USBCTL_PWRDOWN 16 67 #define MAX_USBCTL_CHIPRES 32 68 69 #define MAX_CPUCTL_IE 1 70 71 #define MAX_PINCTL_POSINT_LOW 0 72 #define MAX_PINCTL_POSINT_HIGH 4 73 #define MAX_PINCTL_INTLEVEL_EDGE 0 74 #define MAX_PINCTL_INTLEVEL_LEVEL 8 75 #define MAX_PINCTL_FDUPSPI_HALF 0 76 #define MAX_PINCTL_FDUPSPI_FULL 16 77 78 #define MAX_HIRQ_BUSEVENTIRQ 1 79 #define MAX_HIRQ_RWUIRQ 2 80 #define MAX_HIRQ_RCVDAVIRQ 4 81 #define MAX_HIRQ_SNDBAVIRQ 8 82 #define MAX_HIRQ_SUSDNIRQ 16 83 #define MAX_HIRQ_CONDETIRQ 32 84 #define MAX_HIRQ_FRAMEIRQ 64 85 #define MAX_HIRQ_HXFRDNIRQ 128 86 87 #define MAX_HIEN_CONDETIE 32 88 89 #define MAX_MODE_PERIPHERAL 0 90 #define MAX_MODE_HOST 1 91 #define MAX_MODE_LOWSPEED 2 92 #define MAX_MODE_SOFKAENAB 8 93 #define MAX_MODE_SEPIRQ_OFF 0 94 #define MAX_MODE_SEPIRQ_ON 16 95 #define MAX_MODE_DMPULLDN 64 96 #define MAX_MODE_DPPULLDN 128 97 98 #define MAX_HCTL_SAMPLEBUS 4 99 100 #define MAX_HRSL_JSTATUS 128 101 #define MAX_HRSL_KSTATUS 64 102 103 #define max_reg(n) ((uint8_t) (n << 3)) 104 #define max_reg_read(n) (max_reg(n) | MAX_REG_READ) 105 #define max_reg_write(n) (max_reg(n) | MAX_REG_WRITE) 106 107 #define nanosleep(a, b) if (0) 108 #define usleep(a) if (0) 109 110 struct timespec tCSS = {0, 20}, 111 tL = {0, 30}, 112 tCSW = {0, 200}, 113 tCL = {0, 17}, 114 tCH = {0, 17}, 115 tDS = {0, 5}, 116 tDH = {0, 10}, 117 tDO = {0, 15}, 118 tDI = {0, 15}, 119 tON = {0, 4}, 120 tRESET = {0, 200}, 121 tTEST = {0, 100}; 122 123 void spi_begin() 124 { 125 CLR(MAX_SS); 126 nanosleep(&tL, NULL); /* tCSS is the minimum, but tL is more conservative */ 127 } 128 129 void spi_end() 130 { 131 SET(MAX_SS); 132 nanosleep(&tCSW, NULL); 133 } 134 135 /** 136 * Send the given value via MOSI while receiving a value via MISO. 137 * This requires full-duplex SPI and will produce a status value for the first 138 * value sent (the command). 139 */ 140 uint8_t spi_sendrecv(uint8_t v) 141 { 142 uint8_t result = 0; 143 uint8_t mask; 144 145 for (mask = 0x80; mask; mask >>= 1) 146 { 147 if (v & mask) 148 { 149 #ifdef DEBUG 150 printf("1"); 151 #endif 152 SET(MAX_MOSI); 153 } 154 else 155 { 156 #ifdef DEBUG 157 printf("0"); 158 #endif 159 CLR(MAX_MOSI); 160 } 161 162 /* Wait for stable output signal. */ 163 164 nanosleep(&tDS, NULL); 165 166 SET(MAX_SCLK); 167 168 if (PIN(MAX_MISO)) 169 result |= mask; 170 171 nanosleep(&tCH, NULL); 172 CLR(MAX_SCLK); 173 nanosleep(&tCL, NULL); 174 } 175 176 #ifdef DEBUG 177 printf("\n"); 178 #endif 179 return result; 180 } 181 182 uint8_t max_read(uint8_t reg, uint8_t *status) 183 { 184 uint8_t result = 0, tmpstatus = 0; 185 186 tmpstatus = 0; 187 188 spi_begin(); 189 tmpstatus = spi_sendrecv(max_reg_read(reg)); 190 result = spi_sendrecv(0); 191 spi_end(); 192 193 if (status != NULL) 194 *status = tmpstatus; 195 196 return result; 197 } 198 199 uint8_t max_write(uint8_t reg, uint8_t value) 200 { 201 uint8_t status = 0; 202 203 spi_begin(); 204 status = spi_sendrecv(max_reg_write(reg)); 205 spi_sendrecv(value); 206 spi_end(); 207 208 return status; 209 } 210 211 void chipreset() 212 { 213 printf("Resetting...\n"); 214 max_write(MAX_REG_USBCTL, MAX_USBCTL_CHIPRES); 215 216 printf("Clearing the reset...\n"); 217 max_write(MAX_REG_USBCTL, 0); 218 } 219 220 uint8_t check() 221 { 222 uint8_t oscillator; 223 224 oscillator = max_read(MAX_REG_USBIRQ, NULL); 225 226 return (oscillator & ~(MAX_USBIRQ_NOVBUSIRQ | MAX_USBIRQ_VBUSIRQ)) == MAX_USBIRQ_OSCOKIRQ; 227 } 228 229 uint8_t wait() 230 { 231 uint16_t timeout = 1024; 232 233 /* Wait for the oscillator before performing USB activity. */ 234 235 printf("Waiting...\n"); 236 237 while ((timeout > 0) && (!check())) 238 { 239 usleep(3000); /* 3ms */ 240 timeout--; 241 } 242 243 printf("Iterations remaining: %d\n", timeout); 244 245 return timeout; 246 } 247 248 uint8_t samplebus() 249 { 250 uint8_t result; 251 252 result = max_read(MAX_REG_HCTL, NULL); 253 254 return !(result & MAX_HCTL_SAMPLEBUS); 255 } 256 257 void shutdown(int signum) 258 { 259 printf("Closing...\n"); 260 ubb_close(0); 261 exit(1); 262 } 263 264 int main(int argc, char *argv[]) 265 { 266 uint8_t status = 0, revision = 0; 267 uint16_t count; 268 269 signal(SIGINT, &shutdown); 270 271 if (ubb_open(0) < 0) { 272 perror("ubb_open"); 273 return 1; 274 } 275 276 ubb_power(1); 277 printf("Power on.\n"); 278 279 OUT(MAX_SS); 280 OUT(MAX_MOSI); 281 OUT(MAX_SCLK); 282 OUT(MAX_RESET); 283 IN(MAX_INT); 284 IN(MAX_MISO); 285 286 /* Initialise SPI. */ 287 /* Set SS# to 1. */ 288 289 SET(MAX_SS); 290 CLR(MAX_MOSI); 291 CLR(MAX_SCLK); 292 SET(MAX_RESET); 293 294 /* Initialise the MAX3421E. */ 295 296 /* Set full-duplex, interrupt signalling. */ 297 298 printf("Setting pin control...\n"); 299 max_write(MAX_REG_PINCTL, MAX_PINCTL_INTLEVEL_LEVEL | MAX_PINCTL_FDUPSPI_FULL); 300 301 chipreset(); 302 printf("Ready? %d\n", wait()); 303 304 /* Check various registers. */ 305 306 printf("Mode: %x\n", max_read(MAX_REG_MODE, &status)); 307 printf("IRQ: %x\n", max_read(MAX_REG_HIRQ, &status)); 308 309 /* Set host mode. */ 310 311 printf("Setting mode...\n"); 312 status = max_write(MAX_REG_MODE, MAX_MODE_HOST | MAX_MODE_SEPIRQ_OFF | MAX_MODE_DMPULLDN | MAX_MODE_DPPULLDN); 313 314 printf("Setting INT signalling...\n"); 315 status = max_write(MAX_REG_CPUCTL, MAX_CPUCTL_IE); 316 317 printf("Setting connection signalling...\n"); 318 status = max_write(MAX_REG_HIEN, MAX_HIEN_CONDETIE); 319 320 /* Check various registers. */ 321 322 printf("Mode: %x\n", max_read(MAX_REG_MODE, &status)); 323 printf("IRQ: %x\n", max_read(MAX_REG_HIRQ, &status)); 324 printf("IE: %x\n", max_read(MAX_REG_HIEN, &status)); 325 printf("CPU: %x\n", max_read(MAX_REG_CPUCTL, &status)); 326 printf("Pin: %x\n", max_read(MAX_REG_PINCTL, &status)); 327 printf("USBIRQ: %x\n", max_read(MAX_REG_USBIRQ, &status)); 328 printf("USBIE: %x\n", max_read(MAX_REG_USBIEN, &status)); 329 330 /* Read from the REVISION register. */ 331 332 printf("Reading...\n"); 333 revision = max_read(MAX_REG_REVISION, &status); 334 printf("Revision = %x\n", revision); 335 336 for (count = 0; count <= 65535; count++) 337 { 338 if (!PIN(MAX_INT)) 339 { 340 status = max_read(MAX_REG_HIRQ, NULL); 341 342 if (status & MAX_HIRQ_CONDETIRQ) 343 printf("Device connected.\n"); 344 if (status & MAX_HIRQ_SUSDNIRQ) 345 printf("Suspend done.\n"); 346 if (status & MAX_HIRQ_BUSEVENTIRQ) 347 printf("Bus event.\n"); 348 if (status & MAX_HIRQ_RCVDAVIRQ) 349 printf("Data received.\n"); 350 351 max_write(MAX_REG_HIRQ, status); 352 } 353 } 354 355 printf("Closing...\n"); 356 ubb_close(0); 357 358 return 0; 359 }