gateware

A collection of little open source FPGA hobby projects
git clone http://frotz.net/git/gateware.git
Log | Files | Refs | README

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 }