Merge pull request #178 from elmsfu/hlc/add_symbols_support

hlc: parse '.sym>' to track signal names from HLC to ASC
diff --git a/docs/index.html b/docs/index.html
index 919122e..a8ab14b 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -301,7 +301,7 @@
 <p>
 Recommended reading:
 <a href="http://www.latticesemi.com/~/media/LatticeSemi/Documents/DataSheets/iCE/iCE40LPHXFamilyDataSheet.pdf">Lattice iCE40 LP/HX Family Datasheet</a>,
-<a href="http://www.latticesemi.com/~/media/LatticeSemi/Documents/TechnicalBriefs/SBTICETechnologyLibrary201504.pdf">Lattice iCE Technology Library</a>
+<a href="http://www.latticesemi.com/~/media/LatticeSemi/Documents/TechnicalBriefs/SBTICETechnologyLibrary201608.pdf">Lattice iCE Technology Library</a>
 (Especially the three pages on "Architecture Overview", "PLB Blocks", "Routing", and "Clock/Control Distribution Network" in
 the Lattice iCE40 LP/HX Family Datasheet. Read that first, then come back here.)
 </p>
diff --git a/icebox/icebox.py b/icebox/icebox.py
index 44f6024..f49d7ed 100644
--- a/icebox/icebox.py
+++ b/icebox/icebox.py
@@ -2511,43 +2511,47 @@
         ( 7,  6, 1,  7,  6, 0),
     ],
     "lm4k": [
-        ( 6,  0,  0,  6,  0,  1),
-        ( 6,  0,  1,  6,  0,  0),
-        ( 7,  0,  0,  7,  0,  1),
-        ( 7,  0,  1,  7,  0,  0),
-        ( 8,  0,  0,  8,  0,  1),
-        ( 8,  0,  1,  8,  0,  0),
-        (10,  0,  0, 10,  0,  1),
-        (12,  0,  0, 12,  0,  1),
-        (12,  0,  1, 12,  0,  0),
-        (13,  0,  0, 13,  0,  1),
-        (13,  0,  1, 13,  0,  0),
-        (19,  0,  0, 19,  0,  1),
-        (19,  0,  1, 19,  0,  0),
-        (21,  0,  0, 21,  0,  1),
-        (21,  0,  1, 21,  0,  0),
-        (22,  0,  0, 22,  0,  1),
-        (23,  0,  0, 23,  0,  1),
-        (23,  0,  1, 23,  0,  0),
-        (24,  0,  0, 24,  0,  1),
-        (24,  0,  1, 24,  0,  0),
         ( 4, 21,  0,  4, 21,  1),
         ( 4, 21,  1,  4, 21,  0),
         ( 5, 21,  1,  5, 21,  0),
+        ( 6,  0,  0,  6,  0,  1),
+        ( 6,  0,  1,  6,  0,  0),
         ( 6, 21,  0,  6, 21,  1),
+        ( 7,  0,  0,  7,  0,  1),
+        ( 7,  0,  1,  7,  0,  0),
         ( 7, 21,  1,  7, 21,  0),
+        ( 8,  0,  0,  8,  0,  1),
+        ( 8,  0,  1,  8,  0,  0),
+        ( 9, 21,  1,  9, 21,  0),
         ( 9, 21,  0,  9, 21,  1),
+        (10,  0,  0, 10,  0,  1),
+        (12,  0,  0, 12,  0,  1),
+        (12,  0,  1, 12,  0,  0),
         (12, 21,  1, 12, 21,  0),
+        (13,  0,  0, 13,  0,  1),
+        (13,  0,  1, 13,  0,  0),
         (13, 21,  0, 13, 21,  1),
+        (14,  0,  1, 14,  0,  0),
         (15, 21,  0, 15, 21,  1),
+        (16, 21,  1, 16, 21,  0),
         (17, 21,  1, 17, 21,  0),
         (18, 21,  0, 18, 21,  1),
+        (19,  0,  0, 19,  0,  1),
+        (19,  0,  1, 19,  0,  0),
         (19, 21,  0, 19, 21,  1),
         (19, 21,  1, 19, 21,  0),
+        (21,  0,  0, 21,  0,  1),
+        (21,  0,  1, 21,  0,  0),
         (21, 21,  1, 21, 21,  0),
+        (22,  0,  0, 22,  0,  1),
+        (22,  0,  1, 22,  0,  0),
         (22, 21,  1, 22, 21,  0),
+        (23,  0,  0, 23,  0,  1),
+        (23,  0,  1, 23,  0,  0),
         (23, 21,  0, 23, 21,  1),
         (23, 21,  1, 23, 21,  0),
+        (24,  0,  0, 24,  0,  1),
+        (24,  0,  1, 24,  0,  0),
     ],
     "5k": [
         ( 8,  0,  0,  8,  0,  1),
@@ -4895,6 +4899,56 @@
         ( "F7", 21,  0, 1),
         ( "G3", 13,  0, 0),
         ( "G6", 23,  0, 1),
+    ],
+    "lm4k-cm36": [
+        ( "A1",  5, 21, 1),
+        ( "A2",  7, 21, 1),
+        ( "A3",  9, 21, 1),
+        ( "A4", 16, 21, 1),
+        ( "A5", 19, 21, 1),
+        ( "A6", 22, 21, 1),
+        ( "B1",  4, 21, 1),
+        ( "B2",  6, 21, 0),
+        ( "B3", 12, 21, 1),
+        ( "B4", 13, 21, 0),
+        ( "B5", 21, 21, 1),
+        ( "B6", 23, 21, 1),
+        ( "C1",  7,  0, 1),
+        ( "C5", 23, 21, 0),
+        ( "C6", 23,  0, 0),
+        ( "D1",  6,  0, 1),
+        ( "D6", 24,  0, 0),
+        ( "E1",  7,  0, 0),
+        ( "E2", 13,  0, 0),
+        ( "E3", 14,  0, 1),
+        ( "E5", 22,  0, 1),
+        ( "E6", 24,  0, 1),
+        ( "F1",  6,  0, 0),
+        ( "F2", 10,  0, 0),
+        ( "F3", 12,  0, 1),
+        ( "F4", 19,  0, 0),
+        ( "F5", 22,  0, 0),
+        ( "F6", 23,  0, 1),
+    ],
+    "lm4k-swg25tr": [
+        ( "A1", 22, 21, 1),
+        ( "A3", 13, 21, 0),
+        ( "A4", 12, 21, 1),
+        ( "A5",  5, 21, 1),
+        ( "B1", 21, 21, 1),
+        ( "B5",  6, 21, 0),
+        ( "C1", 23,  0, 1),
+        ( "C2", 19, 21, 1),
+        ( "C4", 13,  0, 0),
+        ( "C5",  7,  0, 1),
+        ( "D1", 24,  0, 0),
+        ( "D2", 23,  0, 0),
+        ( "D3", 19,  0, 0),
+        ( "D5",  6,  0, 1),
+        ( "E1", 24,  0, 1),
+        ( "E3", 12,  0, 1),
+        ( "E4",  7,  0, 0),
+        ( "E5",  6,  0, 0),
     ]
 }
 
diff --git a/icebox/icebox_hlc2asc.py b/icebox/icebox_hlc2asc.py
index 87aafc6..8b82132 100755
--- a/icebox/icebox_hlc2asc.py
+++ b/icebox/icebox_hlc2asc.py
@@ -573,6 +573,9 @@
             if self.device.startswith('1k'):
                 self.ic = icebox.iceconfig()
                 self.ic.setup_empty_1k()
+            elif self.device.startswith('5k'):
+                self.ic = icebox.iceconfig()
+                self.ic.setup_empty_5k()
             elif self.device.startswith('8k'):
                 self.ic = icebox.iceconfig()
                 self.ic.setup_empty_8k()
diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c
index 29d4c22..6462b3d 100644
--- a/iceprog/iceprog.c
+++ b/iceprog/iceprog.c
@@ -2,6 +2,7 @@
  *  iceprog -- simple programming tool for FTDI-based Lattice iCE programmers
  *
  *  Copyright (C) 2015  Clifford Wolf <clifford@clifford.at>
+ *  Copyright (C) 2018  Piotr Esden-Tempski <piotr@esden.net>
  *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
@@ -36,6 +37,23 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
+// ---------------------------------------------------------
+// MPSSE / FTDI definitions
+// ---------------------------------------------------------
+
+/* FTDI bank pinout typically used for iCE dev boards
+ * BUS IO | Signal | Control
+ * -------+--------+--------------
+ * xDBUS0 |    SCK | MPSSE
+ * xDBUS1 |   MOSI | MPSSE
+ * xDBUS2 |   MISO | MPSSE
+ * xDBUS3 |     nc |
+ * xDBUS4 |     CS | GPIO
+ * xDBUS5 |     nc |
+ * xDBUS6 |  CDONE | GPIO
+ * xDBUS7 | CRESET | GPIO
+ */
+
 static struct ftdi_context ftdic;
 static bool ftdic_open = false;
 static bool verbose = false;
@@ -76,6 +94,10 @@
 	MC_CPU_WE = 0x93, /* CPUMode write extended address */
 };
 
+// ---------------------------------------------------------
+// FLASH definitions
+// ---------------------------------------------------------
+
 /* Transfer Command bits */
 
 /* All byte based commands consist of:
@@ -146,6 +168,7 @@
 	FC_GBL = 0x7E, /* Global Block Lock */
 	FC_GBU = 0x98, /* Global Block Unlock */
 	FC_RBL = 0x3D, /* Read Block Lock */
+	FC_RPR = 0x3C, /* Read Sector Protection Registers (adesto) */
 	FC_IBL = 0x36, /* Individual Block Lock */
 	FC_IBU = 0x39, /* Individual Block Unlock */
 	FC_EPS = 0x75, /* Erase / Program Suspend */
@@ -156,6 +179,10 @@
 	FC_RESET = 0x99, /* Reset Device */
 };
 
+// ---------------------------------------------------------
+// MPSSE / FTDI function implementations
+// ---------------------------------------------------------
+
 static void check_rx()
 {
 	while (1) {
@@ -242,9 +269,22 @@
 		data[i] = recv_byte();
 }
 
+static uint8_t xfer_spi_bits(uint8_t data, int n)
+{
+	if (n < 1)
+		return 0;
+
+	/* Input and output, update data on negative edge read on positive, bits. */
+	send_byte(MC_DATA_IN | MC_DATA_OUT | MC_DATA_OCN | MC_DATA_BITS);
+	send_byte(n - 1);
+	send_byte(data);
+
+	return recv_byte();
+}
+
 static void set_gpio(int slavesel_b, int creset_b)
 {
-	uint8_t gpio = 1;
+	uint8_t gpio = 0;
 
 	if (slavesel_b) {
 		// ADBUS4 (GPIOL0)
@@ -270,46 +310,189 @@
 	return (data & 0x40) != 0;
 }
 
+// ---------------------------------------------------------
+// FLASH function implementations
+// ---------------------------------------------------------
+
+// the FPGA reset is released so also FLASH chip select should be deasserted
+static void flash_release_reset()
+{
+	set_gpio(1, 1);
+}
+
+// FLASH chip select assert
+// should only happen while FPGA reset is asserted
+static void flash_chip_select()
+{
+	set_gpio(0, 0);
+}
+
+// FLASH chip select deassert
+static void flash_chip_deselect()
+{
+	set_gpio(1, 0);
+}
+
+// SRAM reset is the same as flash_chip_select()
+// For ease of code reading we use this function instead
+static void sram_reset()
+{
+	// Asserting chip select and reset lines
+	set_gpio(0, 0);
+}
+
+// SRAM chip select assert
+// When accessing FPGA SRAM the reset should be released
+static void sram_chip_select()
+{
+	set_gpio(0, 1);
+}
+
 static void flash_read_id()
 {
-	// fprintf(stderr, "read flash ID..\n");
+	/* JEDEC ID structure:
+	 * Byte No. | Data Type
+	 * ---------+----------
+	 *        0 | FC_JEDECID Request Command
+	 *        1 | MFG ID
+	 *        2 | Dev ID 1
+	 *        3 | Dev ID 2
+	 *        4 | Ext Dev Str Len
+	 */
 
-	uint8_t data[21] = { FC_JEDECID };
-	set_gpio(0, 0);
-	xfer_spi(data, 21);
-	set_gpio(1, 0);
+	uint8_t data[260] = { FC_JEDECID };
+	int len = 5; // command + 4 response bytes
 
+	if (verbose)
+		fprintf(stderr, "read flash ID..\n");
+
+	flash_chip_select();
+
+	// Write command and read first 4 bytes
+	xfer_spi(data, len);
+
+	if (data[4] == 0xFF)
+		fprintf(stderr, "Extended Device String Length is 0xFF, "
+				"this is likely a read error. Ignorig...\n");
+	else {
+		// Read extended JEDEC ID bytes
+		if (data[4] != 0) {
+			len += data[4];
+			xfer_spi(data + 5, len - 5);
+		}
+	}
+
+	flash_chip_deselect();
+
+	// TODO: Add full decode of the JEDEC ID.
 	fprintf(stderr, "flash ID:");
-	for (int i = 1; i < 21; i++)
+	for (int i = 1; i < len; i++)
 		fprintf(stderr, " 0x%02X", data[i]);
 	fprintf(stderr, "\n");
 }
 
+static void flash_reset()
+{
+	flash_chip_select();
+	xfer_spi_bits(0xFF, 8);
+	flash_chip_deselect();
+
+	flash_chip_select();
+	xfer_spi_bits(0xFF, 2);
+	flash_chip_deselect();
+}
+
 static void flash_power_up()
 {
-	uint8_t data[1] = { FC_RPD };
-	set_gpio(0, 0);
-	xfer_spi(data, 1);
-	set_gpio(1, 0);
+	uint8_t data_rpd[1] = { FC_RPD };
+	flash_chip_select();
+	xfer_spi(data_rpd, 1);
+	flash_chip_deselect();
 }
 
 static void flash_power_down()
 {
 	uint8_t data[1] = { FC_PD };
-	set_gpio(0, 0);
+	flash_chip_select();
 	xfer_spi(data, 1);
-	set_gpio(1, 0);
+	flash_chip_deselect();
+}
+
+static uint8_t flash_read_status()
+{
+	uint8_t data[2] = { FC_RSR1 };
+
+	flash_chip_select();
+	xfer_spi(data, 2);
+	flash_chip_deselect();
+
+	if (verbose) {
+		fprintf(stderr, "SR1: 0x%02X\n", data[1]);
+		fprintf(stderr, " - SPRL: %s\n",
+			((data[1] & (1 << 7)) == 0) ? 
+				"unlocked" : 
+				"locked");
+		fprintf(stderr, " -  SPM: %s\n",
+			((data[1] & (1 << 6)) == 0) ?
+				"Byte/Page Prog Mode" :
+				"Sequential Prog Mode");
+		fprintf(stderr, " -  EPE: %s\n",
+			((data[1] & (1 << 5)) == 0) ?
+				"Erase/Prog success" :
+				"Erase/Prog error");
+		fprintf(stderr, "-  SPM: %s\n",
+			((data[1] & (1 << 4)) == 0) ?
+				"~WP asserted" :
+				"~WP deasserted");
+		fprintf(stderr, " -  SWP: ");
+		switch((data[1] >> 2) & 0x3) {
+			case 0:
+				fprintf(stderr, "All sectors unprotected\n");
+				break;
+			case 1:
+				fprintf(stderr, "Some sectors protected\n");
+				break;
+			case 2:
+				fprintf(stderr, "Reserved (xxxx 10xx)\n");
+				break;
+			case 3:
+				fprintf(stderr, "All sectors protected\n");
+				break;
+		}
+		fprintf(stderr, " -  WEL: %s\n",
+			((data[1] & (1 << 1)) == 0) ?
+				"Not write enabled" :
+				"Write enabled");
+		fprintf(stderr, " - ~RDY: %s\n",
+			((data[1] & (1 << 0)) == 0) ?
+				"Ready" :
+				"Busy");
+	}
+
+	usleep(1000);
+
+	return data[1];
 }
 
 static void flash_write_enable()
 {
+	if (verbose) {
+		fprintf(stderr, "status before enable:\n");
+		flash_read_status();
+	}
+
 	if (verbose)
 		fprintf(stderr, "write enable..\n");
 
 	uint8_t data[1] = { FC_WE };
-	set_gpio(0, 0);
+	flash_chip_select();
 	xfer_spi(data, 1);
-	set_gpio(1, 0);
+	flash_chip_deselect();
+
+	if (verbose) {
+		fprintf(stderr, "status after enable:\n");
+		flash_read_status();
+	}
 }
 
 static void flash_bulk_erase()
@@ -317,9 +500,9 @@
 	fprintf(stderr, "bulk erase..\n");
 
 	uint8_t data[1] = { FC_CE };
-	set_gpio(0, 0);
+	flash_chip_select();
 	xfer_spi(data, 1);
-	set_gpio(1, 0);
+	flash_chip_deselect();
 }
 
 static void flash_64kB_sector_erase(int addr)
@@ -328,9 +511,9 @@
 
 	uint8_t command[4] = { FC_BE64, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
 
-	set_gpio(0, 0);
+	flash_chip_select();
 	send_spi(command, 4);
-	set_gpio(1, 0);
+	flash_chip_deselect();
 }
 
 static void flash_prog(int addr, uint8_t *data, int n)
@@ -340,10 +523,10 @@
 
 	uint8_t command[4] = { FC_PP, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
 
-	set_gpio(0, 0);
+	flash_chip_select();
 	send_spi(command, 4);
 	send_spi(data, n);
-	set_gpio(1, 0);
+	flash_chip_deselect();
 
 	if (verbose)
 		for (int i = 0; i < n; i++)
@@ -357,11 +540,11 @@
 
 	uint8_t command[4] = { FC_RD, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
 
-	set_gpio(0, 0);
+	flash_chip_select();
 	send_spi(command, 4);
 	memset(data, 0, n);
 	xfer_spi(data, n);
-	set_gpio(1, 0);
+	flash_chip_deselect();
 
 	if (verbose)
 		for (int i = 0; i < n; i++)
@@ -373,52 +556,72 @@
 	if (verbose)
 		fprintf(stderr, "waiting..");
 
+	int count = 0;
 	while (1)
 	{
 		uint8_t data[2] = { FC_RSR1 };
 
-		set_gpio(0, 0);
+		flash_chip_select();
 		xfer_spi(data, 2);
-		set_gpio(1, 0);
+		flash_chip_deselect();
 
-		if ((data[1] & 0x01) == 0)
-			break;
-
-		if (verbose) {
-			fprintf(stderr, ".");
-			fflush(stdout);
+		if ((data[1] & 0x01) == 0) {
+			if (count < 2) {
+				count++;
+				if (verbose) {
+					fprintf(stderr, "r");
+					fflush(stderr);
+				}
+			} else {
+				if (verbose) {
+					fprintf(stderr, "R");
+					fflush(stderr);
+				}
+				break;
+			}
+		} else {
+			if (verbose) {
+				fprintf(stderr, ".");
+				fflush(stderr);
+			}
+			count = 0;
 		}
+
 		usleep(1000);
 	}
 
 	if (verbose)
 		fprintf(stderr, "\n");
+
 }
 
 static void flash_disable_protection()
 {
 	fprintf(stderr, "disable flash protection...\n");
 
-  //WRSR 0x00
-	uint8_t data[2] = { 0x01, 0x00 };
-	set_gpio(0, 0);
+	// Write Status Register 1 <- 0x00
+	uint8_t data[2] = { FC_WSR1, 0x00 };
+	flash_chip_select();
 	xfer_spi(data, 2);
-	set_gpio(1, 0);
+	flash_chip_deselect();
 	
 	flash_wait();
 	
-	//RDSR
-	data[0] = 0x5;
+	// Read Status Register 1
+	data[0] = FC_RSR1;
 
-	set_gpio(0, 0);\
+	flash_chip_select();
 	xfer_spi(data, 2);
-	set_gpio(1, 0);
+	flash_chip_deselect();
 
-	if(data[1] != 0x00)
+	if (data[1] != 0x00)
 		fprintf(stderr, "failed to disable protection, SR now equal to 0x%02x (expected 0x00)\n", data[1]);
 
 }
 
+// ---------------------------------------------------------
+// iceprog implementation
+// ---------------------------------------------------------
 
 static void help(const char *progname)
 {
@@ -439,6 +642,7 @@
 	fprintf(stderr, "  -o <offset in bytes>  start address for read/write [default: 0]\n");
 	fprintf(stderr, "                          (append 'k' to the argument for size in kilobytes,\n");
 	fprintf(stderr, "                          or 'M' for size in megabytes)\n");
+	fprintf(stderr, "  -s                    slow SPI (50 kHz instead of 6 MHz)\n");
 	fprintf(stderr, "  -v                    verbose output\n");
 	fprintf(stderr, "\n");
 	fprintf(stderr, "Mode of operation:\n");
@@ -509,6 +713,7 @@
 	bool dont_erase = false;
 	bool prog_sram = false;
 	bool test_mode = false;
+	bool slow_clock = false;
 	bool disable_protect = false;
 	const char *filename = NULL;
 	const char *devstr = NULL;
@@ -519,14 +724,15 @@
 		{NULL, 0, NULL, 0}
 	};
 
+	/* Decode command line parameters */
 	int opt;
 	char *endptr;
-	while ((opt = getopt_long(argc, argv, "d:I:rR:e:o:cbnStvp", long_options, NULL)) != -1) {
+	while ((opt = getopt_long(argc, argv, "d:I:rR:e:o:cbnStvsp", long_options, NULL)) != -1) {
 		switch (opt) {
-		case 'd':
+		case 'd': /* device string */
 			devstr = optarg;
 			break;
-		case 'I':
+		case 'I': /* FTDI Chip interface select */
 			if (!strcmp(optarg, "A"))
 				ifnum = INTERFACE_A;
 			else if (!strcmp(optarg, "B"))
@@ -540,10 +746,10 @@
 				return EXIT_FAILURE;
 			}
 			break;
-		case 'r':
+		case 'r': /* Read 256 bytes to file */
 			read_mode = true;
 			break;
-		case 'R':
+		case 'R': /* Read n bytes to file */
 			read_mode = true;
 			read_size = strtol(optarg, &endptr, 0);
 			if (*endptr == '\0')
@@ -557,7 +763,7 @@
 				return EXIT_FAILURE;
 			}
 			break;
-		case 'e':
+		case 'e': /* Erase blocks as if we were writing n bytes */
 			erase_mode = true;
 			erase_size = strtol(optarg, &endptr, 0);
 			if (*endptr == '\0')
@@ -571,7 +777,7 @@
 				return EXIT_FAILURE;
 			}
 			break;
-		case 'o':
+		case 'o': /* set address offset */
 			rw_offset = strtol(optarg, &endptr, 0);
 			if (*endptr == '\0')
 				/* ok */;
@@ -584,25 +790,28 @@
 				return EXIT_FAILURE;
 			}
 			break;
-		case 'c':
+		case 'c': /* do not write just check */
 			check_mode = true;
 			break;
-		case 'b':
+		case 'b': /* bulk erase before writing */
 			bulk_erase = true;
 			break;
-		case 'n':
+		case 'n': /* do not erase before writing */
 			dont_erase = true;
 			break;
-		case 'S':
+		case 'S': /* write to sram directly */
 			prog_sram = true;
 			break;
-		case 't':
+		case 't': /* just read flash id */
 			test_mode = true;
 			break;
-		case 'v':
+		case 'v': /* provide verbose output */
 			verbose = true;
 			break;
-		case 'p':
+		case 's': /* use slow SPI clock */
+			slow_clock = true;
+			break;
+		case 'p': /* disable flash protect before erase/write */
 			disable_protect = true;
 			break;
 		case -2:
@@ -615,6 +824,8 @@
 		}
 	}
 
+	/* Make sure that the combination of provided parameters makes sense */
+
 	if (read_mode + erase_mode + check_mode + prog_sram + test_mode > 1) {
 		fprintf(stderr, "%s: options `-r'/`-R', `-e`, `-c', `-S', and `-t' are mutually exclusive\n", my_name);
 		return EXIT_FAILURE;
@@ -803,33 +1014,40 @@
 	// enable clock divide by 5
 	send_byte(MC_TCK_D5);
 
-	// set 6 MHz clock
-	send_byte(MC_SET_CLK_DIV);
-	send_byte(0x00);
-	send_byte(0x00);
+	if (slow_clock) {
+		// set 50 kHz clock
+		send_byte(MC_SET_CLK_DIV);
+		send_byte(119);
+		send_byte(0x00);
+	} else {
+		// set 6 MHz clock
+		send_byte(MC_SET_CLK_DIV);
+		send_byte(0x00);
+		send_byte(0x00);
+	}
 
 	fprintf(stderr, "cdone: %s\n", get_cdone() ? "high" : "low");
 
-	set_gpio(1, 1);
+	flash_release_reset();
 	usleep(100000);
 
-
 	if (test_mode)
 	{
 		fprintf(stderr, "reset..\n");
 
-		set_gpio(1, 0);
+		flash_chip_deselect();
 		usleep(250000);
 
 		fprintf(stderr, "cdone: %s\n", get_cdone() ? "high" : "low");
 
+		flash_reset();
 		flash_power_up();
 
 		flash_read_id();
 
 		flash_power_down();
 
-		set_gpio(1, 1);
+		flash_release_reset();
 		usleep(250000);
 
 		fprintf(stderr, "cdone: %s\n", get_cdone() ? "high" : "low");
@@ -842,10 +1060,10 @@
 
 		fprintf(stderr, "reset..\n");
 
-		set_gpio(0, 0);
+		sram_reset();
 		usleep(100);
 
-		set_gpio(0, 1);
+		sram_chip_select();
 		usleep(2000);
 
 		fprintf(stderr, "cdone: %s\n", get_cdone() ? "high" : "low");
@@ -877,7 +1095,7 @@
 
 		fprintf(stderr, "cdone: %s\n", get_cdone() ? "high" : "low");
 	}
-	else
+	else /* program flash */
 	{
 		// ---------------------------------------------------------
 		// Reset
@@ -885,11 +1103,12 @@
 
 		fprintf(stderr, "reset..\n");
 
-		set_gpio(1, 0);
+		flash_chip_deselect();
 		usleep(250000);
 
 		fprintf(stderr, "cdone: %s\n", get_cdone() ? "high" : "low");
 
+		flash_reset();
 		flash_power_up();
 
 		flash_read_id();
@@ -925,6 +1144,10 @@
 					for (int addr = begin_addr; addr < end_addr; addr += 0x10000) {
 						flash_write_enable();
 						flash_64kB_sector_erase(addr);
+						if (verbose) {
+							fprintf(stderr, "Status after block erase:\n");
+							flash_read_status();
+						}
 						flash_wait();
 					}
 				}
diff --git a/icetime/Makefile b/icetime/Makefile
index 85d31f8..d260681 100644
--- a/icetime/Makefile
+++ b/icetime/Makefile
@@ -37,7 +37,9 @@
 
 install: all
 	mkdir -p $(DESTDIR)$(PREFIX)/bin
+	mkdir -p $(DESTDIR)$(PREFIX)/share/icebox
 	cp icetime$(EXE) $(DESTDIR)$(PREFIX)/bin/icetime$(EXE)
+	cp ../icefuzz/timings_*.txt $(DESTDIR)$(PREFIX)/share/icebox/
 
 uninstall:
 	rm -f $(DESTDIR)$(PREFIX)/bin/icetime$(EXE)