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