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_USBCTL 15 50 #define MAX_REG_PINCTL 17 51 #define MAX_REG_REVISION 18 52 #define MAX_REG_HIRQ 25 53 #define MAX_REG_MODE 27 54 #define MAX_REG_HRSL 31 55 56 #define MAX_USBIRQ_OSCOKIRQ 1 57 58 #define MAX_USBCTL_PWRDOWN 16 59 #define MAX_USBCTL_CHIPRES 32 60 61 #define MAX_PINCTL_POSINT_LOW 0 62 #define MAX_PINCTL_POSINT_HIGH 4 63 #define MAX_PINCTL_INTLEVEL_EDGE 0 64 #define MAX_PINCTL_INTLEVEL_LEVEL 8 65 #define MAX_PINCTL_FDUPSPI_HALF 0 66 #define MAX_PINCTL_FDUPSPI_FULL 16 67 68 #define MAX_HIRQ_BUSEVENTIRQ 1 69 70 #define MAX_MODE_PERIPHERAL 0 71 #define MAX_MODE_HOST 1 72 #define MAX_MODE_SEPIRQ_OFF 0 73 #define MAX_MODE_SEPIRQ_ON 16 74 #define MAX_MODE_DMPULLDN 64 75 #define MAX_MODE_DPPULLDN 128 76 77 #define max_reg(n) ((uint8_t) (n << 3)) 78 #define max_reg_read(n) (max_reg(n) | MAX_REG_READ) 79 #define max_reg_write(n) (max_reg(n) | MAX_REG_WRITE) 80 81 struct timespec tCSS = {0, 20}, 82 tL = {0, 30}, 83 tCSW = {0, 200}, 84 tCL = {0, 17}, 85 tCH = {0, 17}, 86 tDS = {0, 5}, 87 tDH = {0, 10}, 88 tDO = {0, 15}, 89 tDI = {0, 15}, 90 tON = {0, 4}, 91 tRESET = {0, 200}, 92 tTEST = {0, 100}; 93 94 void spi_begin() 95 { 96 CLR(MAX_SS); 97 nanosleep(&tL, NULL); /* tCSS is the minimum, but tL is more conservative */ 98 } 99 100 void spi_end() 101 { 102 SET(MAX_SS); 103 nanosleep(&tCSW, NULL); 104 } 105 106 /** 107 * Send the given value via MOSI while receiving a value via MISO. 108 * This requires full-duplex SPI and will produce a status value for the first 109 * value sent (the command). 110 */ 111 uint8_t spi_sendrecv(uint8_t v) 112 { 113 uint8_t result = 0; 114 uint8_t mask; 115 116 for (mask = 0x80; mask; mask >>= 1) 117 { 118 if (v & mask) 119 { 120 printf("1"); 121 SET(MAX_MOSI); 122 } 123 else 124 { 125 printf("0"); 126 CLR(MAX_MOSI); 127 } 128 129 /* Wait for stable output signal. */ 130 131 nanosleep(&tDS, NULL); 132 133 SET(MAX_SCLK); 134 135 if (PIN(MAX_MISO)) 136 result |= mask; 137 138 nanosleep(&tCH, NULL); 139 CLR(MAX_SCLK); 140 nanosleep(&tCL, NULL); 141 } 142 143 printf("\n"); 144 return result; 145 } 146 147 void spi_send(uint8_t v) 148 { 149 uint8_t mask; 150 151 OUT(MAX_MOSI); 152 153 for (mask = 0x80; mask; mask >>= 1) 154 { 155 if (v & mask) 156 { 157 printf("1"); 158 SET(MAX_MOSI); 159 } 160 else 161 { 162 printf("0"); 163 CLR(MAX_MOSI); 164 } 165 166 nanosleep(&tDS, NULL); 167 168 SET(MAX_SCLK); 169 nanosleep(&tCH, NULL); 170 CLR(MAX_SCLK); 171 nanosleep(&tDO, NULL); 172 } 173 174 printf("\n"); 175 } 176 177 uint8_t spi_recv() 178 { 179 uint8_t mask, result = 0; 180 181 IN(MAX_MOSI); 182 183 for (mask = 0x80; mask; mask >>= 1) 184 { 185 nanosleep(&tON, NULL); 186 187 SET(MAX_SCLK); 188 189 if (PIN(MAX_MOSI)) 190 { 191 printf("1"); 192 result |= mask; 193 } 194 else 195 printf("0"); 196 197 nanosleep(&tCH, NULL); 198 CLR(MAX_SCLK); 199 nanosleep(&tDO, NULL); 200 } 201 202 printf("\n"); 203 return result; 204 } 205 206 void chipreset() 207 { 208 printf("Resetting...\n"); 209 spi_begin(); 210 spi_sendrecv(max_reg_write(MAX_REG_USBCTL)); 211 spi_sendrecv(MAX_USBCTL_CHIPRES); 212 spi_end(); 213 214 printf("Clearing the reset...\n"); 215 spi_begin(); 216 spi_sendrecv(max_reg_write(MAX_REG_USBCTL)); 217 spi_sendrecv(0); 218 spi_end(); 219 } 220 221 uint8_t wait() 222 { 223 uint8_t status = 0, oscillator = 0; 224 225 /* Wait for the oscillator before performing USB activity. */ 226 227 printf("Waiting...\n"); 228 229 while (!oscillator) 230 { 231 spi_begin(); 232 spi_send(max_reg_read(MAX_REG_USBIRQ)); 233 oscillator = spi_recv(); 234 spi_end(); 235 236 oscillator = oscillator & MAX_USBIRQ_OSCOKIRQ; 237 if (!oscillator) 238 usleep(3000); /* 3ms */ 239 } 240 241 return status; 242 } 243 244 void reset() 245 { 246 SET(MAX_RESET); 247 nanosleep(&tRESET, NULL); 248 CLR(MAX_RESET); 249 } 250 251 int main(int argc, char *argv[]) 252 { 253 uint8_t status = 0, revision = 0, hrsl = 0; 254 255 if (ubb_open(0) < 0) { 256 perror("ubb_open"); 257 return 1; 258 } 259 260 ubb_power(1); 261 printf("Power on.\n"); 262 263 OUT(MAX_SS); 264 OUT(MAX_MOSI); 265 OUT(MAX_SCLK); 266 OUT(MAX_RESET); 267 IN(MAX_INT); 268 IN(MAX_MISO); 269 270 /* Initialise SPI. */ 271 /* Set SS to 1 (or SS~ to 0). */ 272 273 SET(MAX_SS); 274 CLR(MAX_MOSI); 275 CLR(MAX_SCLK); 276 CLR(MAX_RESET); 277 278 /* Initialise the MAX3421E. */ 279 280 reset(); 281 wait(); 282 283 /* Set full-duplex, interrupt signalling. */ 284 285 printf("Setting pin control...\n"); 286 spi_begin(); 287 spi_sendrecv(max_reg_write(MAX_REG_PINCTL)); 288 spi_sendrecv(MAX_PINCTL_INTLEVEL_LEVEL | MAX_PINCTL_FDUPSPI_FULL); 289 spi_end(); 290 printf("INT set to %d\n", PIN(MAX_INT)); 291 292 /* Set host mode. */ 293 294 printf("Setting mode...\n"); 295 spi_begin(); 296 spi_sendrecv(max_reg_write(MAX_REG_MODE)); 297 spi_sendrecv(MAX_MODE_HOST | MAX_MODE_SEPIRQ_OFF | MAX_MODE_DMPULLDN | MAX_MODE_DPPULLDN); 298 spi_end(); 299 printf("INT set to %d\n", PIN(MAX_INT)); 300 301 /* Read from the REVISION register. */ 302 303 printf("Reading...\n"); 304 spi_begin(); 305 status = spi_sendrecv(max_reg_read(MAX_REG_REVISION)); 306 revision = spi_sendrecv(0); 307 spi_end(); 308 printf("Status = %x\n", status); 309 printf("Revision = %x\n", revision); 310 printf("INT set to %d\n", PIN(MAX_INT)); 311 312 /* Detect bus event. */ 313 314 if (status & MAX_HIRQ_BUSEVENTIRQ) 315 { 316 printf("Clearing BUSEVENTIRQ...\n"); 317 spi_begin(); 318 status = spi_sendrecv(max_reg(MAX_REG_HIRQ)); 319 spi_sendrecv(MAX_HIRQ_BUSEVENTIRQ); 320 spi_end(); 321 printf("Status = %x\n", status); 322 } 323 324 printf("HRSL...\n"); 325 spi_begin(); 326 status = spi_sendrecv(max_reg_read(MAX_REG_HRSL)); 327 hrsl = spi_sendrecv(0); 328 spi_end(); 329 printf("Status = %x\n", status); 330 printf("HRSL = %x\n", hrsl); 331 printf("INT set to %d\n", PIN(MAX_INT)); 332 333 printf("Closing...\n"); 334 ubb_close(0); 335 336 return 0; 337 }