Category Archives: Projects

Lattice FPGA programming adapter from the junk box

Working with Lattice FPGAs recently, I had a need to program one but couldn’t find my ‘proper’ (Chinese clone, bought from eBay) programming adapter. When I started the Diamond Programmer software, though, it claimed it could see a USB programming adapter. It turned out that I’d left an FTDI ‘FT2232H Mini Module‘ attached to the PC. I use the module for all sorts of little debugging exercises: most often as a dual serial port for serial port debugging, but it also works for programming Parallax Propeller microcontrollers.

Img_0603

As luck would have it, the Diamond software recognises the unadulterated FT2232H as a legitimate USB programmer, and pressing the ‘Detect Cable’ button finds it. Note that if you plug in a new USB device, the Diamond Programmer software needs restarting before it can see it.

The FT2232H has two ports, A and B, and these appear as ports FTUSB-0 and FTUSB-1 in the Diamond software. All that remained was to figure out the wiring. Fortunately, there are a lot of clues in the schematics of various Lattice evaluation boards, particularly the MachXO2 Pico Board and the iCE40 Ultra Breakout Board.

diamond-programmer

Here’s the wiring, both for SPI and JTAG, referred to the pins on the Mini Module. I chose to use port B since it was more convenient for my prototype board. Translating the wiring to port A is left as an exercise for the reader.

SPI    JTAG  FT2232H  Mini Module
SO     TDI   DBUS1    CN3-25
SI     TDO   DBUS2    CN3-24
SCK    TCK   DBUS0    CN3-26
SS_B   ISPEN DBUS4    CN3-21
CRESET TRST  DBUS7    CN3-18
GND    GND   GND      CN3-2,4

It works well, and does exactly what it should.

Advertisements

First steps with a Lattice iCE40 FPGA

I’ve just been doing some work with the iCE40 series of FPGAs from Lattice Semiconductor. They’re small FPGAs, with up to 7680 gates, and they’re very low-power, which is nice for mobile applications. From what I can gather, Lattice acquired the designs when they bought a company called SiliconBlue in 2011. I’ve been used to using the Lattice Diamond software with their other chips, but the iCE40 chips aren’t supported by Diamond. Instead, they get their own software called iCEcube2. It’s a bit of a pain to use and not very well documented. I’ve just been through the process of starting a project and getting a very basic design working, and I’m writing about it here in case someone else finds it useful.

Img_0602

The iCEcube2 software looks convincingly like an IDE, but it isn’t, really. It doesn’t even seem to have a way of creating new source code files, and the order in which some things have to be done is not at all obvious. I think iCEcube2 is really designed for taking existing designs and implementing them on the Lattice iCE40 chips. While the software is a complete dog’s breakfast, it does have the key advantage of being free. You do need to create a node-locked licence for it using their licencing page.

iCEcube-blank

To start an empty project, double click Project -> New Project. Select the chip you’re going to use. This creates a folder with the title of the project, containing:

  • <project>_sbt.project
  • <project>_syn.prj
  • folder <project>_Implmnt, containing folder sbt, containing folders constraint, log and outputs. All are empty apart from iceCube0.log in log folder.

Now you can add your source files. If you click on ‘Synthesis Tool’, then an ‘Add Synthesis Files’ menu item appears, but clicking on this doesn’t do anything useful. You have to right-click on ‘Add Synthesis Files’ and select ‘Add Files…’ from the pop-up menu. Go figure. I used a very simple VHDL source file:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY test IS
 PORT
 (
 d: in std_logic;
 q: out std_logic;
 qn: out std_logic
 );
END test;

ARCHITECTURE rtl OF test IS
BEGIN

 q <= d;
 qn <= not d;
 
END rtl;

At this point I’d expect to be able to allocate signal names (d, q and qn, in this case) to pins on the device package. But you can’t do that yet in the wonderful world of iCEcube2. All the buttons on the toolbar are greyed out. The way to proceed is to double click ‘Run Synplify Pro Synthesis’. Hopefully your code will compile without errors, and lots of files get created.

The project folder now contains:

  • stdout.log and stdout.log.bak
  • synlog.tcl
  • loads of stuff under <project>_Implmnt

Two new files appear in the project under ‘P&R Flow’: <project>.edf and <project>.scf.

Now double-click ‘Run P&R’. The design will get placed and routed, and a bitmap gets generated for programming the chip.

At this point the toolbar buttons for timing constraints, pin constraints, floor planner, package view, power estimator and timing analysis become active. Hurrah! Now you can change your pin constraints.

iCEcube-toolbar-enabled

Click on ‘Pin Constraints Editor’, the fourth icon from the left. Put in the pin locations for the signals you want. Make sure you click the ‘locked’ checkboxes on the left hand side, otherwise the place and route process is likely to move them. Press ctrl-S to save. The constraints get saved in <project>_Implmnt\sbt\constraint\<top design file>_pcf_sbt.pcf. You will then get asked to add the file to the project. Say yes.

If you’re using source control, it’s a good idea to add this file to it. I’m not so sure about all the other junk that iCEcube generates.

Now double-click ‘Run P&R’ again and the new bitmap file will be generated, using your pin constraints.

Programming an actual chip (or at least its SPI Flash ROM) needs the Diamond Programming tool, which comes as part of the Lattice Diamond software and *not* as part of iCEcube2. That’s just another couple of gigabytes to download, and another licence (free) to acquire, so it’s a pain, but it does work.

Orange Internet and port forwarding, continued

A long time ago, I wrote an article about how I worked around the lack of NAT loopback support on the Orange LiveBox broadband router. At the time, it was a pain to get everything working right. Having just moved house, we made the sensible decision to stay with the same broadband provider, in order to avoid having to re-invent or at least re-configure all this stuff.

Well, it turned out not to be as easy as that. Nothing ever is, it seems. The new Orange broadband service comes with a ‘FunBox‘ instead of a ‘LiveBox’. Fun? Who said? Not in my experience. The web interface to the box looks comfortingly similar to the old LiveBox, so I thought it would work the same way. No chance.

funbox2

What’s the problem I’m trying to solve here? Well, I have a little SheevaPlug which hosts some services I need to use from various locations when I’m working. Yes, I know I should put those services ‘in the cloud’, but that would involve both paying money and solving a whole load of other problems. For years and years, I’ve simply had a port forwarding rule set up on my home broadband router so that the SheevaPlug is accessible from the internet. A little touch of dynamic DNS courtesy of dyn.com and it’s all worked fine.

Fast forward to 2015. I tried to recreate the setup I’d always used, but with the FunBox (hah!). The old setup went like this:

home_net_old

  • the broadband router just does the usual NAT routing and behaves as a dumb wi-fi access point. It has a port forwarding rule set up to forward port 22 (ssh) to the SheevaPlug
  • the SheevaPlug hosts my ssh server, and provides the DHCP and DNS services to everything on the network, so I get proper local hostname lookups, easy-to-manage IP addresses, and can solve the NAT loopback problem.

That’s it. I tried to set up the FunBox the same way. What could possibly go wrong?

I boldly switched off the DHCP and DNS servers in the FunBox and switched over to using the ones on my SheevaPlug. Everything seemed to work fine, except…the TV. Yes, the TV decoder is connected to the FunBox via Ethernet, so the whole shebang comes down the wire. No aerial required. Trouble is, the FunBox seems to need to set up the TV decoder by DHCP otherwise it doesn’t know it’s there, so you get no telly. Oh well, I’ll use the DHCP server in the FunBox and put up with the inconvenience.

Even that doesn’t work out. In order to solve the NAT loopback problem, which the miserable FunBox suffers from just like the LiveBox, I need to run my local DNS server. Except that the brain-dead FunBox won’t let you change the DNS settings on its built-in DHCP server. How annoying is that?

OK, accept that NAT loopback will remain a problem. Maybe I’ll find another way round that. Now for the showstopper: the blessed FunBox refuses to forward port 22. It will forward every other port under the sun, but not 22. The web configuration interface just won’t accept the setting: it ignores it. Doesn’t even give an error message. You’re just not having it. Oh well, maybe I have to expose my ssh server on a different port and put up with changing all the gazillion clients which know about it. Except I’ve still got the loopback problem. This is getting unpleasant.

Before tearing out what little remained of my hair by this point, I slept on the problem and had a brainwave. The FunBox supports a ‘DMZ’ feature, in which it’ll forward all incoming internet traffic to a particular IP address on the LAN. I tried it, experimentally sending all internet traffic to the poor, naked SheevaPlug, and it worked! At last, sweet relief: something which does what it says on the tin.

Clearly exposing the server in all its complacent insecurity to the internet isn’t a good idea. I needed to put a firewall in the way. A rummage in the cupboard produced a spare Raspberry Pi and a USB to Ethernet adapter. I programmed OpenWRT on to an SD card and booted up. It turned out to be easier to configure it through the command line than with the web interface, LuCI, which isn’t exactly finished yet. Some fiddling later and I’d managed to disable its DHCP and DNS features and enable incoming connections only on port 22.

Adding the firewall had another bonus: it meant I could re-enable my DNS and DHCP servers and let them look after the LAN without the wretched FunBox knowing anything about it. It just has to live a simple life, looking after the telly and the firewall. I disabled its built-in Wi-fi access point and added an ageing Linksys WAP54G running DD-WRT software after the firewall. Lovely.

home_net_new

There is one fly in the ointment: the Raspberry Pi turns out to make a rubbish router. Our 30 megabit internet connection is reduced to 3 megabits on its way through the Pi. I don’t know if it’s something to do with my configuration, or the release of OpenWRT (15.05-rc3) I’m using. When I’ve unpacked enough boxes to find another router, I’ll try that.

Servicing a Fluke 12 Multimeter

One of my most-used tools on the workbench is my Fluke ’12’ multimeter. I’ve had it almost 20 years, and it’s my favourite meter because it was clearly designed by someone who had to fix things. It’s rugged, especially in its bright yellow holster, and has so many thoughtful features: it has big buttons and a switch, instead of a rotary knob, so it’s easy to use with one hand. It autoranges quickly and reliably. In continuity and resistance modes, it automatically switches to measuring voltage if it detects one, so you don’t need to worry about changing ranges when debugging things. It doesn’t have fiddly extra features. It doesn’t even have a current range, because it would make no sense: measuring current usually involves breaking a circuit, which you can’t easily do when working on a circuit board. It switches itself off when unused for half an hour or so, saving the battery.

Img_0007

It’s been completely reliable apart from needing a new set of test leads last year (for the first time). However, recently the big, chunky buttons had become reluctant to respond, and needed firmer and firmer presses until they didn’t work at all. That meant I was stuck measuring either DC voltage or continuity. Time to pull it apart and see what’s wrong.

Removing the test leads and holster, then taking out the four screws, reveals the view you get when changing the battery. I’m sure Dave at EEVBlog, master of the multimeter teardown, would approve. Lots of chunky components and very solid construction.

Img_0008

The PCB is held in by the plastic clips at the top and sides. Easing them back lets it and the plastic frame underneath it come out:

Img_0010

The black plastic internal frame (under the PCB in this photo) is marked as being made of polycarbonate, so it’s very strong. None of that high-impact polystyrene rubbish. It’s nice that the membrane for the buttons bears against the frame, not straight against the PCB. This is nice industrial design.

The button membrane is connected by a zebra strip to the PCB. The PCB itself looks nice and clean, and the zebra strip is OK, but the contacts on the membrane look tarnished.

Img_0012

I wanted to test the membrane using the continuity check function of my trusty Fluke 12…oh, hang on, it’s in pieces. Break out the equally trusty Avo 8.

Img_0013

The membrane itself works fine. I cleaned up the contacts using DeoxIT D5 on a piece of paper. I also cleaned all the plastic parts, including the holster, in the office sink with washing-up liquid. Here’s the result, showing resistance mode to prove that the buttons work.

Img_0014

Looking good, working as well as it did when new, and ready for the next 20 years.

Calculating days of the week on a Propeller

I’m doing a project using a Parallax Propeller microcontroller at the moment. It’s like a normal microcontroller, but psychedelic. Eight cores, peripherals defined almost entirely in software, and primarily programmed in a cunning language called Spin. Spin is a very efficient interpreted language and makes it possible to squeeze a lot into the Propeller’s meagre 32K of RAM.

The project has a real-time clock maintained by an off-the-shelf clock chip, but this application needs to know the day of the week as well. Of course, I can get the user to set the day of the week when they set the clock, but it’s unintuitive to have to set it manually, and this thing is supposed to be easy to use.

IMG_0006

I looked in to algorithms for calculating the day of the week given a year, month and date. There are loads of them. The Wikipedia page has lots, and this Stackoverflow page has a load of useful suggestions. There was one particularly simple one which appeared in both places, credited to Tomohiko Sakamoto on the comp.lang.c Usenet newsgroup in 1993. I don’t care about the theory behind the algorithm, I just want it to work and to be simple to program in Spin. The original is in C and looks like this:

dayofweek(y, m, d)	/* 1 <= m <= 12,  y > 1752 (in the U.K.) */
    {
        static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
        y -= m < 3;
        return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
    }

My Spin version looks like this:

DAT
 dayTable BYTE 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4

PRI decFromBCD(n)
 return (n&$f)+10*((n&$f0)>>4)

PRI calcDayFromDate | y
 y := decFromBCD(year) + 2000
 if month < 3
   y--

 day := (y + (y/4) - (y/100) + (y/400)
       + dayTable[decFromBCD(month)-1]
       + decFromBCD(date)) // 7

Mine looks more complex, and the one reason for that is that the clock chip maintains its counts in BCD (binary-coded decimal) rather than straight decimal. There might be a cunning way to modify the algorithm to take BCD values directly, but I took the easy route of implementing a function which converts an 8-bit BCD value into decimal.

The code assumes the presence of three variables: year (0 to 99, starting at the year 2000), month (1 to 12) and date (1 to 31) and sets a variable day in the range 0 to 6, where 0 is Sunday.

When implementing the clock in your project, don’t forget to compensate for the leap second tonight.

Solidlights new LED upgrade

The first Solidlights products to be sold used the Lumileds Luxeon III LEDs, which were state of the art back in 2003. Technology has moved on since then, however, and modern LEDs are much more efficient – they produce a lot more light for the same amount of electricity. Though I’m no longer actively developing Solidlights, I occasionally tinker with upgrades to the ones I use regularly.

For a year or so now I’ve been using a modified Solidlights 1203D dynamo light fitted with Cree XP-G2 LEDs. Getting the best from them requires modifications to the lenses, too, but it’s worth it: the theoretical maximum light output from each LED is 488 lumens, whereas the old Luxeon III could only manage about 80 lumens. I’ve done the modification informally for a couple of customers, too, and they’ve been happy with it.

xpg2

There’s been more interest recently, so I’ve made this upgrade available in the Solidlights on-line shop. It’s listed as part number 99002 under ‘service and repairs’.

Sideways RAM for BBC Micro Model B+

There’s an excellent article by Mark at RetroClinic on adding 32K of Sideways RAM to a BBC Micro with just a couple of track cuts and wires. I’ve performed it on a BBC Model B, in order to replace a Solidisk SWR which never worked reliably even when it was new, and the modification works well. However, I wanted to do it on the BBC B+ I use in the office, and the details are slightly different.

The first thing to note is that the B+’s sideways ROM sockets are conveniently already wired to support 32K chips (27256 EPROMs). There is a row of links to the left of the ROM sockets which select whether each socket is configured for a 16K chip or 32K chip. Each link just selects whether pin 27 (A14 on 27256, /PGM on 2764 and 27128) is tied to +5V or connected to the bottom bit of the ROMSEL register IC45. If the link is to the left, pin 27 is tied high, and if it’s to the right, it’s an address bit. To be honest I can’t see any reason not to leave them all to the right all the time, since pulling /PGM low on 2764 and 27128 chips seems to have no effect other than disabling the chip. However, on my B+ they were all set to the left by default.

The layout of the parts on the board is:

    +------+ +------+ +------+
S19 |      | |      | |      |
S18 | IC62 | | IC68 | | IC71 |
S15 | ROM  | | ROM  | | OS & |
S12 | banks| | banks| | bank |
S11 | 8/9  | | A/B  | | 1/F  |
S9  |      | |      | | BASIC|
    | (S15)| | (S18)| | (S19)|
    +------+ +------+ +------+
    +------+ +------+ +------+
    |      | |      | |      |
    | IC35 | | IC44 | | IC57 |
    | ROM  | | ROM  | | ROM  |
    | banks| | banks| | banks|
    | 2/3  | | 4/5  | | 6/7  |
    |      | |      | |      |
    | (S9) | | (S11)| | (S12)|
    +------+ +------+ +------+

Note that S19 (for IC71) behaves a bit differently. IC71 is always the OS ROM, which is not a sideways ROM, but can be a sideways ROM (in bank 1 or bank F) as well. If S19 is placed to the right, IC71 should have the OS in the top 16K and a sideways ROM image, conventionally BASIC, in the bottom 16K. Which bank this ROM image ends up in depends on the setting of S13. If S13 is set ‘north’, the lower half of IC71 appears in bank 1. If it’s ‘south’, it appears in bank F. Normally bank F is convenient for BASIC.

The key ingredient of the sideways RAM upgrade is to provide a write enable signal to the RAM chip. This isn’t normally present on ROMs because it makes no sense to write to a ROM. The RetroClinic upgrade takes a write signal from IC77 pin 8. This is the write strobe for the uPD7002 ADC and the 8271 floppy disc controller. The corresponding signal still exists in the B+, and is used by the ADC and the 1770 floppy disc controller. It comes from IC27 pin 6, however, which is conveniently close to the ROM sockets.

However, there’s an annoying difference between a 27256 32K EPROM and a 62256 32K RAM. The EPROM has A14 on pin 27, but the RAM has A14 on pin 1 and /WE, the write enable signal, on pin 27.

On the Model B, it’s not hard to cut the tracks to pins 1 and 27 and solder wires on the bottom of the board. However on the B+, the tracks to those pins are on the top of the board, mostly concealed by the socket, and are a royal pain to get to. I could have desoldered the socket, done the modifications and put it back, but that was relatively risky and a lot of effort. I decided to just take pins 1 and 27 of my RAM chip outside the socket and run a wire from pin 27 to IC27 pin 6, and pin 1 to IC45 pin 14 (the source of the address line), on the top of the board. Here’s what it looked like.

DSC_1094

My final discovery was that the Sideways RAM utilities are provided by the 1770 DFS ROM. My B+, however, only had DFS version 2.10, which doesn’t include them. I programmed a ROM with DFS version 2.26, and took the opportunity to shuffle the existing ROMs into 32K chips to save sockets.

This done, the SRAM commands were now available, but the Sideways RAM wouldn’t work. I’d put my RAM chip in socket IC57, which is banks 6 and 7. It seems that the B+ and DFS SRAM utilities only understand about Sideways RAM in the banks which the B+128 would have it: banks 0, 1, C and D, exactly the banks which are not covered by the ROM sockets. Doh!

I needed to move my RAM chip to appear in banks 0 and 1. This was easily accomplished by moving pin 20 outside the socket and soldering a wire from it to IC46 pin 15. IC46 is the address decoder for the ROM sockets, and pin 15 is its /0 output.

Now, when switched on, the machine shows ‘Acorn OS 96K’ (cute!) instead of its previous ‘Acorn OS 64K’, and the *SRLOAD command works to load images into banks 0 and 1.

Img_8121s

In summary, to add 32K of Sideways RAM to a BBC B+ 64K:

  • Move S12 into its right-hand position
  • Bend pins 1, 20 and 27 of a 62256 RAM chip so they fall outside the socket
  • Put the chip with bent pins into socket IC57
  • Solder a wire from pin 1 to IC45 pin 14
  • Solder a wire from pin 20 to IC46 pin 15
  • Solder a wire from pin 27 to IC27 pin 6
  • Make sure your DFS is version 2.26

Now you have Sideways RAM in banks 0 and 1. Job done.

IMG_8120