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