An improved micro:bit CPU

In a previous project I made a simulation of a very simple microprocessor using a BBC micro:bit.

It’s coded in MakeCode blocks and, although it only has 4 instructions in its very reduced instruction set, it behaves in many ways like the microprocessors as used in the very first home computers, pioneering machines like the Altair 8800, the MOS Technology / Commodore Kim-1 and the Science of Cambridge MK14:

  • Instead of being programmed with a high-level language like MakeCode, Scratch, Python or BASIC, its instructions are given using binary codes.
  • Each binary code represents an instruction, an instruction with a piece of data attached (in this case an address where it should fetch some data from), or just a piece of data.
  • When the program is run, the CPU fetches each instruction in turn from memory.
  • It then decodes the instruction – it decides what the instruction means.
  • The CPU next executes the instruction – it carries it out.
  • It keeps track of where it is in the program using a program step counter and adds 1 to the program counter every time it needs to get a new instruction.
  • It keeps fetching, decoding and executing instructions in order from memory until it reaches a halt instruction.

In effect, all our very simple CPU can do is add two numbers together and display the answer in binary using LEDs. It’s little more than a calculator, and not a very good one as it can’t subtract, multiply or divide.

It’s restricted to only 4 instructions because of the way I designed each word:

micro:bit CPU instruction set

I limited myself to a 5-bit binary word, rather than the 8 bits as more normally used in early computer systems, because I wanted to be able to show the contents of each memory location on a row of the micro:bit’s LED display, with a lit LED representing a 1 and an unlit LED representing a 0.

Because I decided to store the operand (data, in this case an address) in the last 3 bits of instructions, that only left the first two bits to encode the actual instruction – the opcode.

This is clearly a bad idea, but if I still want to keep a 5-bit word to fit the display, I can split the opcode from the operand, and that’s what version 2 of my micro:bit CPU project does.

New CPU – new instructions

Now in my new design when the CPU fetches and decodes an instruction that needs an operand (some data or an address where it can find the data), it interprets the next address in memory as data, not an instruction. It does this by reading its contents and increasing the program step counter by 2 instead of by 1.

Now we have 5 whole bits to encode instructions, we can have not 4 but 31 instructions. Strictly speaking we could have 32, but I decided to treat myself and make 00000 a no operation opcode, an instruction that does nothing.

31 sounds like a lot, but even early 8-bit processors like the 6502 used in early home computers had over 100 instructions. To keep this project simple, but still do something more useful, I decided to use the minimum number of instructions I needed to implement a simple algorithm for multiplication:

multiplication algorithm using addition

This algorithm multiples 6 (held in variable x) by 7 (held in y) by adding 6 to variable a 7 times. It also deducts 1 from y each time, and when y reaches zero, the loop stops and it shows the answer on the LED display output,

To make this work in my micro:bit CPU, as well as the addition I can already do, I’m going to need the ability to reduce a variable by 1. Reducing something by 1 is called decrementing. Being able to increment and decrement numbers is useful when doing repetitive tasks, as we’ll see.

This very simple algorithm, however, requires two more things missing from our original micro:bit CPU:

  • The ability to loop over sets of instructions.
  • The ability to make a decision based on a condition – in this case, if y is zero, break out of the loop.

The second of these, the ability to change which code is executed depending on the result of a calculation, is fundamentally what makes a computer a computer, rather than just an adding machine. This ability to branch, to take different paths though sets of instructions, is also what separated Charles Babbage’s Analytical Engine from the simpler Difference Engine and made the Analytical Engine, although it was never built, theoretically a general-purpose computer.

For simplicity, I’ve decided to put the loop and the ability to jump out of a loop together in one instruction: JUMP IF NOT ZERO.

When any decrement instruction results in the number 0, a flag is set. Microprocessors have words of memory set aside to store several flags: these are single bits that record things like reaching zero (a zero flag), going into negative numbers (a negative flag) or numbers being too big to store in one word (a carry flag).

Our new CPU program uses a MakeCode variable zeroFlag as its zero flag. It’s a Boolean variable, which means like a microprocessor’s flag, it can only have two values, true or false, 1 or 0.

Here’s our new instruction set:
new instruction set

I could have added some registers or a stack to store data, and I may do that in a future version, but to keep things simple I only made one – A, or the accumulator. You can store numbers in it or add numbers to it. You can also increment or decrement contents of memory locations – so in effect you can use as many memory locations as variables or registers as you like.

As I develop this, I’ll probably add the ability to subtract numbers from the accumulator and the ability to store the accumulator in memory locations as well as store and add numbers directly.

We don’t use all of these instructions in our multiplication program, though, Here it is, a program to multiply 5 by 6 by adding 5 six times:

multiplication program written in binary codes

It adds the number 5 into our accumulator. It finds the number 5 by looking in the memory location specified in the next bit of memory: it tells the CPU to fetch the number from memory location 8.

Next it decreases the contents of location 9 by 1. This is so it can keep track of how many 5s we’ve added.

The instruction in memory location 4 tells it to jump back to location 0 if the zero flag has not been set. It keeps doing this until the zero flag is set when memory location 9 reaches zero.

Next it outputs the result, the number in the accumulator, as a binary number using the LEDs on the bottom row of the display. It then reaches the HALT instruction and stops decoding and executing any further instructions or data,

What’s the clock speed?

My micro:bit CPU doesn’t have a clock to keep fetching instructions, it relies on you to keep pressing button B to step through the program. Press button A to put the CPU in execute mode so that instead of just showing the contents of memory on the top row of LEDs, it will execute any instructions as well.

Diagram of the micro:bit CPU interface

Try it out for yourself in the simulator below. Press button A to put it in program execute mode. You’ll hear a high tone as it starts. Keep pressing button B and you’ll see it loop around the same locations – it keeps adding 5 to the accumulator and reducing memory location 9 by 1 each time it does this. It adds 5 six times, and 5 lots of 6 is 5 x 6 or 30. When memory location 9 reaches 0, it shows the result of 5×6 in binary on the bottom row of the display and when it gets to the halt instruction it plays a low tone.

You can keep pressing button B but the program won’t execute – the program run LED has gone out and it won’t decode or execute any instructions any more.

Here’s the code that makes it work – quite a complex program, but I’ve tried to use functions where I can to make it easier to follow.

Open it in the MakeCode editor and see if you can create your own program for the improved micro:bit CPU!

Posted in microbit | Tagged , , , | Leave a comment

Make your own processor with a micro:bit

Last week I made a binary adding machine out of 3 micro:bits to learn a bit about how computers work deep inside.

This week I’ve been inspired by Ben Eater’s 8-bit computer project. I highly recommend his videos if you want to learn how computers work at a really fundamental level. He has one project where he builds a simple computer on a breadboard using a 6502 processor, the same processor used by the first computer I ever used, my big brother’s Kim-1, as well as more famous machines like the Commodore PET, Commodore 64, Apple 2, BBC Micro, Atari games consoles and the Nintendo Entertainment System.

Kim-1-computerVery early (and relatively inexpensive) home computers in the 1970s, like the Kim-1 or the Science of Cambridge MK-14, were not even like the home computers of the 1980s. These were single-board computers, uncased like a Raspberry Pi is today but they didn’t, initially at least, hook up to your TV, nor did they have a typewriter keyboard. They just had hexadecimal calculator-like number keypads and simple LED displays of the kind you also found on the calculators of the day.

You didn’t program them in a high-level, easy-to-read language like BASIC or Python, either. You programmed them in assembly language: short very simple commands (usually in the form of 3-letter ‘mnemonics’) that each had their own hexadecimal number value that you entered using the keypad. This was very hard, slow and required a lot of planning and patience, but it meant that you were writing code that ran very quickly indeed on the ‘bare metal’ of the CPU (central processing unit). BASIC programs running on the same processors like the 6502 ran much more slowly, because your English-like BASIC commands had to be translated into something the processor could understand (machine code) every time it ran.

A very simple assembly language program might look like this:

start LDX #$FF    ; load X with $FF = 255
loop  DEX         ; X = X - 1
      BNE loop    ; if X not zero then goto loop
      RTS         ; return

All that program does is count down from 255 to 0 in a register – it doesn’t even output it.

Although it’s much harder to read that assembly language program than a BASIC or Python program, it’s easier to read than machine code. The processor can only understand numbers, so to actually enter the program above into a singe-board computer like the Kim-1 would require you to translate each instruction into its equivalent number code, so your program would become a string of hexadecimal numbers like

A2 FF CA D0 FD 60

that you had to enter using the calculator keypad. You would do the translation by hand using a chart, or if you were lucky and had a more advanced computer, a program called an assembler would translate the assembly language to machine code for you.

Ben Eater’s breadboard computers are like this, and as well as his 6502-based project, he also makes his own processor using logic gates on breadboards to build a really simple computer, and that’s what fired my imagination. Could you create your own processor with a small instruction set using a micro:bit?

This is what I came up with.

A micro:bit CPU

I decided my micro:bit CPU would be a 5-bit computer, rather than 8-bit as you might expect. This is because I want to show the contents of memory, instructions and so on using the LEDs on the micro:bit’s display, which is made up of 5 rows of 5.

Diagram of the micro:bit CPU interface

The top row of LEDs shows the program counter as a binary number. Dark LEDs are zeroes, lit LEDs are ones. Here the number is 00010 in binary, or step 2 in base 10. This counts up as we step through the program.

Unlike a real CPU, we’re not going to use a clock to automatically step through instructions, we’re going to do this manually by pressing button B.

The middle row shows the contents of the memory at the address shown on the top row, again as a binary number. So here we see that memory location 00010 contains 10000.

The bottom row is the output. This is blank until we write something to it, which as it happens this program just has, because 10000 is an instruction code to write the contents of a register (like a variable) to the display output.

How do we know 10000 means ‘write contents of register A to the output display’? Because that’s how our micro:bit processor is designed. Even simple microprocessors have dozens of instructions, but ours is only going to have 4:

micro:bit CPU instruction set

It’s only got 4 because remember I’ve decided only to use a 5-bit word, and if I’m going to be able to include any meaningful address data I think I need at least 3 bits to store the address (the red Xs in the table above). That only leaves 2 bits for actual instructions.

You can think of the first two binary digits as the opcode (operation code, or instruction), and the last 3 digits as the operand (the data that will be manipulated by the opcode).

I’ve decided my processor can load the contents of a memory slot into a register called A. This is, in effect, a variable. It can also add the contents of another memory location to it. It can output the contents of A. Finally, the Halt instruction tells it to stop executing the program. We need this because we want to use memory slots after our program code to contain data like the numbers we’re going to add, and we don’t want the processor trying to execute the data as if it were an instruction.

The code

our micro:bit CPU program

It loads the contents of memory location 4 into register A. It then adds the contents of location 5 to it, shows it on the display output and stops. In effect, it’s adding 12 and 11 and showing the result as a binary number on the micro:bit’s LED display.

Try it out in the simulator

The code for this project is in this HEX file (right click and ‘save link as…’ or ‘save target as…’ to download it). You will (at the time of writing) need to load it in the beta version of MakeCode because it uses some new blocks.

Press button B to step through each memory location to check the program. Reset the simulator and press button A to switch on execute mode. You should see the execute flag light come on. Now when you step through the program using button B it will execute any data as instructions until it reaches a Halt instruction. Keep pressing button B and you should see the number 23 appear in the bottom row as binary 10111.

A little bit of history repeating

4 instructions is a very reduced instruction set, but Reduced Instruction Set Computers (RISC) were, and are, a thing. In the late 20th century, people realised that processors with reduced instruction sets were faster and used less power, meaning you could run them on batteries in portable devices. One company doing this was a British one called ARM. They designed the processor that went in early mobile computers like the Apple Newton. Today almost every smartphone has an ARM-designed CPU in it, as indeed does the BBC micro:bit.

You may not know that the A in ARM originally stood for Acorn: Acorn RISC Machines. Acorn made the BBC Micro, a computer widely-used in UK schools in the 1980s. It was also quite a popular home computer, and it used the same 6502 processor used by the Apple, Commodore and Atari computers of the time. The BBC Micro was part of a digital literacy scheme including TV programmes, and this was echoed by the 2016 BBC Make It Digital campaign which introduced the micro:bit. So ARM were involved in both projects, and indeed they are founding partners of the Micro:bit Educational Foundation.

How does it work?

cpu code blocks

I’ve used what is still at the time of writing a beta version of MakeCode for this project because it allows functions that pass back parameters. I go into a little more detail in the video, but the main elements are:

  • the memory is made up of binary numbers stored as text strings in an array
  • the PgmCounter variable tracks where you are in the program – this is a normal base 10 MakeCode variable
  • functions convert between base 10 (denary) integers and binary number strings and vice versa, returning a value
  • a function displays any binary number string on any specified row on the LED display
  • the CPU function contains the code that fetches, decodes and executes instructions just like in a real processor

Here’s the function that converts from binary to base 10. The CPU function uses this to translate binary memory addresses and data into base 10 so we can use normal MakeCode maths functions and array addresses. Let’s unpack how this works.

The binary number is held as a text string, so the loops steps though every character for however long the number is. The easiest way to convert from binary to base 10 is to identify the place value for each digit and add them up:

binary number system

The function does just that. It keeps a running total of the base 10 value in the dec variable.

Notice that each place value (1, 2, 4, 8, 16 etc) can be written as powers of 2. 1 is 2 to the power of 0, 2 is 2 to the power of 1, 4 is 2 to the power of 2, then 3 and 4. The function uses that fact to do the conversion in very few blocks of code.

It uses char from text at index to look at each binary character in term.

If it finds a ’1′ character, it uses its place in the binary number string to work work out which power of 2 to add to the base 10 total.

Because it’s going from left-to-right, from most significant (largest) bit to smallest, we need to a bit of jiggery-pokery to reverse the list and work out the power needed.

MakeCode function to convert binary to base 10
(This is a simplified and improved version of the function actually used in the project).

I wasn’t sure how to do this, so I wrote out a table a bit like this to see if I could spot the pattern and find how to convert the location of a digit to its place value as expressed as powers of 2. If we can spot a pattern, we can write a compact bit of code to do the conversion:

pattern spotting in binary to base 10 conversion

So, we need to convert the character string index to the power, convert 0 to 4, 1 to 3, 2 to 2 and so on – and it would be neat to do this for any length string.

The pattern I spotted was that the power is equal to the length of the binary number string minus the index plus 1. We have to add 1 because string character indices are zero-indexed – the first character is character number 0.

Next steps

Let me know if you have ideas for improving this or if you find it. useful for understanding or teaching how CPUs and simple systems work.

One idea I have is to split the instruction and address data, allowing many more instructions – 32 in fact – and the ability to create much more useful programs that have more maths functions and which can include ‘if’ statements by jumping to different memory locations depending on the results of calculations.

You may also like…

If this sparked your interest, check out this awesome project: https://github.com/veryalien/mycobit. It’s a 4-bit micro:bit CPU, written in Python, that you can program using the micro:bit’s own buttons, so it’s self-contained and doesn’t need a computer. It has a useful instruction set and gives access to GPIO pins. I look forward very much to playing with this, and perhaps magpie-ing some instruction set ideas for the next version of my MakeCode micro:bit CPU.

And check this out! I just learned about another micro:bit CPU program written in Python (and indeed in Croatian) by Ivan Bosnić that uses actual written opcodes / mnemonics: https://github.com/bosnivan/CPPU. If you don’t speak Croatian, you can still work out what the instructions do.

Posted in computers, hardware, microbit | Tagged , , | 6 Comments

micro:bit binary adding machine

I’m going to how to show you to turn two or more micro:bits in to a binary adding machine, using the same code on every micro:bit.

The ability to add two numbers together is a fundamental building block of any calculating machine. If you can add, you can multiply as multiplication is repeated addition. If you can add, you can probably subtract, and that means you can do division as well, as division can be thought of as repeated subtraction.

But the ability to add numbers is ALSO fundamental to building computers. As well as solving maths problems, adding numbers enables computers to find data in memory, step through lists of instructions as well as more exciting things like moving a space ship across your screen in a game.

Electronic circuits that can do sums – and do them very quickly – are called adders. Lots of them are wired together to form the Arithmetic Logic Unit in the processor at the heart of every computer, tablet, phone and many electronic devices like TVs and washing machines.

base 10 counting system

Humans usually count in a system based around the number 10 – because we have 10 fingers. We use 10 different symbols, 0 through to 9 to record numbers. Each column is worth 10 times more than the one to its right. This is called base 10, or denary.

binary place values

on / off symbolComputers, on the other, er, hand, use the binary system, which just uses two symbols: 0 and 1. This is because computers are made up of millions of tiny switches, and a switch can be used to store binary numbers: off means 0, and on means 1. This is why the on/off power symbol used on many devices is a zero with a 1 inside!

AND gate made of switches

So switches form the circuits that make up computers, by making logic gates. Logic gates take simple binary inputs, on or off, 0 or 1, and make different outputs. Some are simple, like AND gates. These give an output only if both its inputs are switched on.

OR gate made of switches

The OR gate, on the other hand, will give an output if EITHER of its inputs are turned on.

xor gate truth table

The EXCLUSIVE OR gate gives an output if either input is switched on – but not both.

Why do you need to know that? Because logic gates like these make up computer memory but also are the building blocks of the Arithmetic Logic Unit, the part of the processor that does all the maths, all the number crunching.

If you connect up an AND logic gate and an XOR gate, you can use it to add two binary numbers together. This is called a half adder. Each switch is a 0 or 1 depending on whether it’s turned on or off. The lights show the sum – if a light’s on it’s 1, if it’s off it’s 0.

Half adder working

You’ll see that both switches off – 0 + 0 – means no lights are lit – binary 00.

If either switch A or B is, the sum light is lit, but not the carry – binary 01.

If both A and B are switched on, we’re adding 1+1. The answer is 10. Why 10? Well it doesn’t mean ten, it means no units, and 1 two – the answer to 1+1 is 2!

half adder made of 6 micro:bits

Last year I made a project using 6 micro:bits to simulate a half adder – though you could replace the two input micro:bits with real switches to use just 4 micro:bits instead. We have separate micro:bits acting as an AND and XOR gate, taking real electrical signal inputs, processing the inputs and producing outputs that add two numbers together.

Of course a micro:bit contains thousands of actual logic gates, so it IS a bit crazy to turn one into a single logic gate, but it’s interesting to code it, and connect all the parts together to make the most fundamental part of any computer system.

That’s only adding two single-digits together, though, and it uses a lot of micro:bits. So I’ve made another project – a full adder on a single micro:bit.

A full adder has not two, but three inputs – A, B and a Carry In. As well as the two numbers you’re adding, the Carry In takes the Carry Out from a neighbouring adder, just as you add in any numbers you carry when doing column addition in base 10 arithmetic.

So you can add together as many full adders as you like to allow you to add really big numbers together. Every single adder you, er, add, makes the largest number you can add twice as big.

how to connect micro:bit full adders together

So, here’s how you connect it together: use as many micro:bits as you like, and the same code goes on every one. Turn them on their side. Pin 1 is the Carry Out, so connect it to pin 0 – the Carry In – on the micro:bit to its left and keep going until you run out of micro:bits.

That leaves us with one carry out left over, no matter how many micro:bits we use. But we don’t need to let it go to waste! If you have an LED lying around, connect its long leg (the anode) to the final carry out, and its short leg to GND. While you’re there, connect all the GND pins together, to complete the electrical circuit.

You could power each micro:bit individually from batteries or USB, and indeed it’s safer to do that, but I’ve been a bit cheeky here. I’ve only powered the far micro:bit on the right, and powered all the others from it by joining their 3 volt pins together. If you connect many more than 3 together this probably wouldn’t work.

Here’s how to use it.

micro:bit adders joined together

The top row of A switches make up the first number we’re going to add. The LED dot in the top right of each display shows you if the switch is on or off, it toggles every time you press it.

The row of B switches across the bottom make up the second number, and the LED in the bottom right shows you if it’s on or off.

To add 1 + 1 set the top and bottom rows to 001 and you can see the result: 010 in binary, which is 2 in base 10.

You’ll see another light has lit up on the micro:bit in the 2s column. That’s to show that it’s received the carry bit from its neighbour.

Ok, let’s do some more adding. 2 + 2. That 010 and 010 in binary. And the answer is 100, we’ve got no units, no twos and one four.

How about 5 + 5? That’s 101 and 101 – the answer is ten of course in base 10. We only have 3 micro:bit numbers, but notice our carry LED is now lit on the far left, meaning the number is 1010 in binary. One eight, and one two. 8 + 2 = 10. The right answer!

Let’s look at how my micro:bit full adder works. The same program goes on every micro:bit in the adder, no matter how many you have, just like a real adder uses identical circuits chained together.

It uses two variables to store the value of A and B, but instead of giving them numerical values of 0 or 1, I’m using TRUE or FALSE. TRUE means 1 and FALSE means 0. I set both to FALSE, off, zero at the start of the program.

Calling 0 false and 1 true is also common when talking about logic gates and circuits. The charts that show how logic gates work are called truth tables.

Another reason for using true and false for 1 and 0 here is that it makes it really easy to flip each variable’s value when you press a button with ‘set A to not A’ and ‘set B to not B’ – if each variable is 0 or 1, it flips to the other value when you press the button.

To keep the code easy to follow, I’ve made a function – a subroutine – to turn the relevant LEDs on and off to show the values of A and B.

As with many computer programs, the real business goes on inside the infinite loop, the forever block in MakeCode.

I’ve used another function here as a subroutine – this one keeps checking if it’s receiving any carry bits from next door. If it is, it lights the carry in LED and sets the carryIn variable to True. If not, it turns the LED off and carryIn’s value will be False.

Now, the real heart of the program is in the big if… then… block.

Rather than implementing it purely as the wired logic gates, I looked at the truth table for a full adder and worked from the bottom up.

If all the inputs are turned on, we’re adding 1 + 1 + 1 we have 11 in binary, so we need to show 1 on the display, and turn on the carryOut signal so it gets added to the next column.

If A and B are 1 and Cin is 0 (not Cin means Cin is false, or 0), we have 1+1 = 10 in binary – we need to show 0 on the display and turn on the carry out signal.

If either A or B is 1 AND Cin is 1, it’s the same thing, 1+1, so we provide the same output, 0 in the display and carry one out to the next column.

We’re running out of options now. If any one of A, B or Cin is 1, we only have 1, so let’s show a 1 on the display and turn off the carry out signal.

If none of those cases is true, we must have no numbers at all, and 0 + 0 + 0 is 0 in any counting system, so the display shows 0 and there’s nothing to carry out to the next column.

As my micro:bits are on their sides, I’ve used functions to draw the sideways 0s and 1s on the LED display.

If you make an adding machine using this program do let me know, or if you have ideas for further improving it!

Posted in computers, hardware, microbit | Tagged , , , | Leave a comment

Radio clock

Screen shot of the word clock

BFH (Broadcasting From Home) is quite the thing these days, so I thought I’d make a web version of the clocks used in radio studios. These spell out the time in easy-to-read words, and remove the brain-gymnastics required to turn an analogue or digital clock into something you’d actually say out loud.

Some radio presenters are legendary for their time-telling skills, other less so. I once worked with one who forgot his co-presenter’s name as he introduced her on air at the start of the programme, but frankly I’m amazed that anyone talking to millions of people at stupid o’clock in the morning can remember their own name, let alone tell the time.

So, I present my radio clock: http://suppertime.co.uk/radio-clock/

Some things to note:

  • It’s only as accurate as your computer, tablet or phone’s clock and will always follow its time.
  • It’s written in JavaScript about which I know little – suggestions for its improvement are very welcome.
  • This means if you lose your internet connection, the clock will keep running. Although, unless you’re using ISDN, you’ve probably fallen off air at that point.
  • This also means you can view the source code, download and host it locally on your computer, tinker with it and improve it. If you re-share it, please credit me.
  • It looks ok on my laptop and on my phone in portrait mode – suggestions very welcome for improving its mobile performance in landscape especially.
  • It should handle half past, quarter to, quarter past, midday and midnight.
  • If it’s one minute to or past the hour, quarter hours of half hour it’ll say ‘almost…’ or ‘just gone…’
  • If it’s buggy or you think of a new feature, please let me know!

Along with my Raspberry Pi cartwall and audio play-out programs, I hope you find this a valuable addition to your home studio.

Posted in radio | Tagged , , | Leave a comment

Hyper-local personal train and London bus times

Terence Eden has a cool project to turn a Nook e-reader into a personal display of the next useful trains and London buses to depart from near his home.

I thought I’d do something similar and would start with the PHP / web page end. I’ll skip the Nook bit for now, and just bookmark this page on my phone so I have trains and buses on one page. It only shows trains with platforms allocated (i.e. that may run any time soon) more than 10 minutes in the future – to allow me time to get to the station – and buses more than 2 minutes away (the bus stop is closer!)

I had a few issues:

  • I want to host it on my hosting company’s server which is in a different time zone, so I had to add code to compensate for that
  • It runs an ancient version of PHP and not all of Terence’s code would work
  • It really wasn’t happy about slurping in the bus data from another site
  • I wanted to add two different train routes from different stations as different people in our house have completely different journeys to make

So I cooked up a hideous kludge* that is half-PHP, half-JavaScript. JavaScript seems to have no compunctions about slurping London bus data from TfL.

The code is over on GitHub: https://github.com/blogmywiki/travel

If you want to do something similar, the index.php file works for me with PHP version 5.3

If you don’t have access to a webserver running PHP (whether via a hosting company or a Raspberry Pi running on your home network), and you live in London, you could still use the JavaScript portion of index.php and run the file as pure html on your own computer just to get the bus data.

You’ll need to modify a few things to get it to work:

  • get your own National Rail data API key from here and add it to index.php: http://realtime.nationalrail.co.uk/OpenLDBWSRegistration
  • change the 3-letter station codes; the first should be your nearest station, the second where you want to go to
  • use the CSV file to find the ‘Naptan_Atco’ code for your nearest bus stop and plug that in to the JavaScript section of the index.php (line 227)
  • modify the time offsets to only show trains you can catch for each station, depending on how long it takes you to get to each station (lines 134 & 198)
  • modify 120 on line 236 (120 = 2 minutes) to equal how long it takes to walk to your bus stop
  • make sure the OpenLDBWS.php file is in the same directory as index.php

The buses are sorted in order of next arrival, but you could tidy this up by only showing each route once with the times for that bus. And I really should filter out platform 6, going to London Bridge via Slade Green makes no sense at all…

Posted in computers | Tagged , , , , , | Leave a comment