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