icetool.c (3160B)
1 // Copyright 2015 Brian Swetland <swetland@frotz.net> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <unistd.h> 19 #include <ctype.h> 20 21 #include "ftdi.h" 22 23 #define GPIO_CS_N 0x10 24 #define GPIO_CDONE 0x40 25 #define GPIO_CRESET_N 0x80 26 27 #define GPIO_DIR 0x93 28 29 static unsigned char mpsse_init[] = { 30 FTDI_LOOPBACK_OFF, 31 FTDI_CLOCK_DIV_5, 32 FTDI_DIVISOR_SET, 0x00, 0x00, // 6MHz 33 FTDI_GPIO_WRITE_LO, 1 | GPIO_CS_N | GPIO_CRESET_N, GPIO_DIR, 34 }; 35 36 // send CS1 8x0 CS0 <data> CS1 8x0 37 int spi_tx(FTDI *d, void *data, int len) { 38 u8 cmd[13 + 4096 + 7]; 39 40 // RST=1 CS=1 41 cmd[0] = FTDI_GPIO_WRITE_LO; 42 cmd[1] = 1 | GPIO_CRESET_N | GPIO_CS_N; 43 cmd[2] = GPIO_DIR; 44 // TX 8x 0 45 cmd[3] = FTDI_LSB_TX_BYTES_TN, 46 cmd[4] = 0; 47 cmd[5] = 0; 48 cmd[6] = 0; 49 // RST=1 CS=0 50 cmd[7] = FTDI_GPIO_WRITE_LO; 51 cmd[8] = 1 | GPIO_CRESET_N; 52 cmd[9] = GPIO_DIR; 53 // TX n 54 cmd[10] = FTDI_LSB_TX_BYTES_TN, 55 cmd[11] = len - 1; 56 cmd[12] = (len - 1) >> 8; 57 58 if (len > 4096) 59 return -1; 60 memcpy(cmd + 13, data, len); 61 memcpy(cmd + 13 + len, cmd, 7); 62 if (ftdi_send(d, cmd, 13 + len + 7, 1000)) 63 return -1; 64 return 0; 65 } 66 67 void usage(void) { 68 fprintf(stderr, 69 "usage: icetool -load <addr> <hexfile>\n" 70 " icetool -write <addr> <value>...\n" 71 ); 72 exit(1); 73 } 74 75 int main(int argc, char **argv) { 76 u16 addr; 77 u16 data[2049]; 78 int n; 79 FTDI *d; 80 int do_cls = 0; 81 82 if (argc == 2) { 83 if (!strcmp(argv[1], "-cls")) { 84 do_cls = 1; 85 goto doit; 86 } 87 } 88 if (argc < 4) { 89 usage(); 90 } 91 if (!strcmp(argv[1], "-load")) { 92 char buf[1024]; 93 addr = strtoul(argv[2], 0, 16); 94 FILE *fp = fopen(argv[3], "r"); 95 if (fp == NULL) { 96 fprintf(stderr, "cannot open '%s'\n", argv[3]); 97 return 1; 98 } 99 n = 0; 100 while (fgets(buf, 1024, fp)) { 101 if (!isalnum(buf[0])) continue; 102 if (n == 2048) return 1; 103 data[1 + n++] = strtoul(buf, 0, 16); 104 } 105 fclose(fp); 106 } else if (!strcmp(argv[1], "-write")) { 107 addr = strtoul(argv[2], 0, 16); 108 argc -= 3; 109 argv += 3; 110 n = 0; 111 while (argc > 0) { 112 if (argv[0][0] == '/') { 113 char *s = argv[0] + 1; 114 while (*s != 0) { 115 if (n == 2048) return 1; 116 data[1 + n++] = *s++; 117 } 118 } else { 119 if (n == 2048) return 1; 120 data[1 + n++] = strtoul(argv[0], 0, 16); 121 } 122 argc--; 123 argv++; 124 } 125 } else { 126 usage(); 127 } 128 doit: 129 if ((d = ftdi_open()) == NULL) { 130 return 1; 131 } 132 if (ftdi_send(d, mpsse_init, sizeof(mpsse_init), 1000) < 0) { 133 return 1; 134 } 135 136 if (do_cls) { 137 memset(data + 1, ' ', 64 * 2); 138 for (int y = 0; y < 30; y++) { 139 data[0] = 0x8000 + y * 64; 140 spi_tx(d, data, (64 + 1) * 2); 141 } 142 } else { 143 data[0] = addr; 144 spi_tx(d, data, (n + 1) * 2); 145 } 146 147 return 0; 148 }