0

A lesson learned

Posted by Chris on Tuesday, December 29, 2009
Something that has been bugging me for a little while now is the backlight on our ScoreSure Golf Pro device. It works fine when a 3V3 supply is put to it. But the PIC microcontroller can't provide enough current to drive it directly from one of the output pins. So we've been using a transistor (an NPN BP199 from Farnell if you must know) to switch the backlight on and off via an output pin on the mcu.

It works, but we've never been 100% happy with it.
The backlight comes on, but it's noticeably dimmer when the transistor is used, compared to just connecting power to the LED anodes. But we've got to the bottom of it - it's all to do with using the microcontroller to "sink" or "source" the power to the backlight LEDs.

Here's how to use an mcu and transistor to "source" current for the LED backlight:


When the PIC micro backlight output pin is high, the transistor allows current to flow from the power source into the LCD backlight LED anode (LCD_A+).

Here's how to use an mcu and transistor to "sink" current for the LED backlight:


In this example, the power is always connected to the backlight LED anode (LCD_A+), but the transistor only allows current to flow from the LED cathode (LCD_K-) to ground when the PIC backlight output pin is high. This is known as "sinking" current.
The two switching techniques both work - only "sinking" the current makes the LCD light up nice and brightly, whereas when "sourcing" current through the transistor, the LCD does light up, but more dimly.

0

Did Santa bring all you asked for?

Posted by Chris on Monday, December 28, 2009
We asked for a completed, working schematic, a website, an online golf course editor and a way of getting full-colour images to display on the screen, instead of 16-colour images with their nasty jaggedy edges.

Working late into the night on Xmas Eve, we finally got the full-colour images working, with beautifully drawn, smooth-edged hand-drawn pictures of golf holes on the little LCD screen. (Actually they're not full-colour, but 128-colour-palette images, but you can break a large image up into pieces and get near-photo-quality results with each piece using just 128 colours per image).

But that was all we had time for, for a few days - with family and work commitments (had a brilliant Xmas by-the-way) - development has stalled and will probably remain that way until after the New Year (even nerds get invited to New Years Eve parties you know!)



0

Video of ScoreSure Golf Pro progress

Posted by Chris on Wednesday, December 23, 2009
Now we're getting somewhere - not just photos of LCDs with boring old text and plain old rectangles, or photos of random images (that don't draw properly). Here's an actual real video of the actual, real device doing something actual (and real).
It's showing the golf hole and image data for the first few holes from the Whitefields Golf Course. That's real, actual data, don't you know!

0

The photo we've been waiting to see....

Posted by Chris on Monday, December 21, 2009


Here's a screenshot that we've all been waiting to see (well, at least those of us involved with the development of the latest version of ScoreSure). It's showing the ScoreSure Golf Pro with details for the first golf hole from the Whitefields Golf Course. Check out the details on the online scorecard. Hole 1 really is called the Flyover and the par for the hole, for blue white and yellow tees really is 4. And the stroke index for hole one, when playing off red tees, really is 15.

All this information has been loaded into Flash/eeprom memory and is pulled out when the device is in "run" mode. But never mind how accurate the information is or isn't (it is, actually!) just take a look at how beautiful it looks.....

0

A week is a long time in politics

Posted by Chris on Wednesday, December 16, 2009
...but a mere microsecond when you're working on a technology project with a looming deadline. We've not had much time to update the blog lately, but that's because things have been happening (and changing) at quite a pace over in Nerd Towers.
We're on a mission to get the first ScoreSure Golf Pro prototype developed and working, which has meant lots of late nights and early mornings, and hundreds, nay thousands of lines of code being written and re-written.

The big panic is because our mate Xing from NuElectronics is over in China for Xmas, and we've a fantastic opportunity to actually get some real, working prototypes made up.
Not a bread-board prototype (which is what we use for development) but an actual, final product, in a professionally finished enclosure and a fancy little wallet!

All this, of course, means that we actually have to settle on a final design for the schematics and that in turn has meant ironing out lots of little bugs and issues. For example, making sure that the Flash memory is connected to a consistent port and whether lines we've tied to power/ground may need to be controlled in future developments. It's a balancing act - getting enough done to meet today's demands, but trying to think about what might be needed in future versions of the product so we can re-use the same products and not have to re-develop the entire thing for a minor change.

The biggest obstacle we've had is stream-writing data to the Flash eeprom chip.
We thought we had this nailed, but when drawing bitmaps back to the screen there were missing pixels in the image. We put this down to a dodgy bitmap drawing routine and decided it would be easily fixed. It turns out, that the problem was actually with the Flash/memory writing routines and we had big gaps in our bitmap data!

That in turn has meant rebuilding the device pretty much from the ground up to try to isolate where the problem stemmed from (after all this, there was a bug in the VB app we used to send data to the ScoreSure device, not the actual device itself!). It was a worthwhile exercise, however, because our written design - the electrical schematic we sent for production - has changed quite a bit since we've gone back and had to re-think everything.

But - finally - we have a working ScoreSure device. One that can display menus as well as bitmaps. You can even edit menu entries so we have a mechanism for editing player details.

We're off to fill up on coffee and get back to the grindstone.
In the meantime, here's a screenie showing working bitmaps on the QVGA LCD screen.



And for regular readers of the blog, who may be asking "what about the online Google-maps-based golf course editor"? (all two of you) here's a link to try out latest development: http://www.scoresure.co.uk/googlemaps.htm

0

No posts for a while...

Posted by Chris on Tuesday, December 08, 2009
...which can only mean plenty of activity up at Nerd Towers.
And you'd be right - we're busy working away on an online golf course editor. Yes, yes, we've already done one of those. But this time, it's different.
This time, not only do you get to drop trees and bunkers onto a pre-made map shape, but you're actually drawing the map that appears on the ScoreSure device itself!

After the partial-success of the bitmap drawing routines we had to decide which would be the best format for saving/displaying bitmaps on the device. RLE (run-length-encoded) bitmaps are nice and quick to draw, use up very little memory - both on the microcontroller and in storage - but lead to very small colour palettes. True-colour images are possible, but take up huge amounts of storage, cannot be buffered or loaded into RAM and are quite slow to draw onto the screen (streaming a single pixel of data from eeprom via two calls to extract two bytes means drawing the screen is quite slow).

So then we got to thinking about RLE bitmaps and how they could be used to draw things like sprites. And then we figured, it would be nice if we could make full use of our colour screen by displaying a little digital map of each hole as they are played. And then we thought "that's a lot of work, creating bitmaps and accurate data for all holes on all golf courses, all over the world!". So what better way to offload some of this workload, than to give the user the tools to create their own golfing maps?

They wouldn't even have to stick to designated golf courses. Got a mini-golf in your back garden? You could create your own online golf course and download it onto your ScoreSure device. Suddenly, there are a world of opportunities - and all because users can create their own maps. What we need is a Flash-based golf-course editor!

Here's how it works:
Find your favourite golf course using the integrated Google Maps editor.
Click the appropriate button(s) to select which "layer" you're going to draw on (there's a separate layer for the fairway, the green, and any bunkers/water)
Draw shapes over the top of the Google Map (changing the transparency to allow other layers to show through as necesasry). In the example, below, you can see we've started drawing the putting green.

When you're happy with your colouring in, hit the "next" button (currently "save") and you get the change to rotate, resize and generally mess about with your map, to get it to fit inside a window that will fit on the ScoreSure screen (at the time of writing, 100x240 pixels).


One of the holes at Whitefields Golf Course, Thurlaston, Rugby in the map editor

With the map in place, facing the right way up and so on, you can then drag and drop the rest of the "furniture" in place - trees, flag, teeing off points and so on.
The idea is that whatever you put together in the Flash editor will be used to recreate the map EXACTLY on your ScoreSure Golf Pro handheld device.

So if anyone has any disagreements with the maps on the device (a range of ready-made maps will be made available for download from the ScoreSure Golf website) they can go off and create their own!

1

More progress on QVGA displays

Posted by Chris on Thursday, December 03, 2009
There's a pretty typical pattern emerging here - a few days with no blog posts = flurry of activity "offline" in the real world. And that's exactly what's been going on this time around too. We've been working like a room full of monkeys (not eating bananas and throwing poo around, more like the monkeys that sit with the typewriters banging out the works of Shakespeare) to get some pictures on the LCD screens.
And finally, we think we've cracked it.
Have a look at this - it's the opening screen for the ScoreSure device.



And here it is, actually displayed on the QVGA LCD.



See? Exactly the same.
Well, ok, maybe there's a bit more work to do on this one.
The missing stripes of data could be one of two things:
a) The code drawing the image from Flash to the LCD is screwed up or
b) the more likely option, sending data from the PC to the Flash memory is dodgy

But it's definitely a picture. And it definitely nearly looks like the picture we want to it. So once again, a bit more work and I'm sure we'll have it cracked....

2

QVGA progress

Posted by Chris on Sunday, November 29, 2009
It seemed pretty obvious, we'd got a rectangle drawn on screen, we'd got some characters drawn on the screen, the next logical step was to put some characters on top of a rectangle. Drawn correctly, a few lines of characters drawn over a rectangle could look just like a menu.



How about that then?
A few tweaks to the current PIC code, and we're now able to draw menus, with highlighted items. In fact, we've pretty much built a menu-drawing "library", allowing menus to be drawn anywhere on the screen, any size, with any number of entries (as many as the screen will allow at least).
We've also fixed the bug when drawing characters, so they all have lovely nice outlines around them and can be drawn on any coloured background.

To date, we've got a procedure which takes the following variables and draws a working menu:
menu_x
menu_yco-ordinates on the screen to draw the menu at
menu_width
menu_heightthe background rectangle of a menu can be set to any size
backcolourcolour of the background rectangle
forecolourfont colour drawn over the menu rectangle
menubar_highlightcolour of the "stripe" to draw on the highlighted menu item

When it's hooked up to eeprom, we'll be able to add in stuff like "what to do when a menu item is selected". But that will have to wait - as soon as the Flash eeprom is hooked up, we've got bitmaps to draw.......

UPDATE: Check out our YouTube video showing the menu in action:
http://www.youtube.com/watch?v=sBe5wHwwa0c

2

Progress so far

Posted by Chris on Friday, November 27, 2009
Well, whenever you get any graphical screen working, the first job is always to write a repeating message - "Nerds are cool" or something like that.
And to display a message on a graphical screen, you need to have a "bitmap" font - a sequence of bytes that, when sent to the display, create letters on screen.

We've chosen the "BlackoutX" font as it has a thick outline around each character, making it ideal for dark and light backgrounds. It also happens to be a fixed width font (always easier for implementing bitmap-based text) and even better, each character is 8x8 pixels in size. It's just like a custom ZX Spectrum font!

Note to uber-nerds and ZX Spectrum bores: poke 23606,x and poke 23607,y where x and y are the high/low bytes pointing to the start address where your character set has been poked into memory. It's amazing what you remember, even decades later....


The outline around each of the characters also mean that this font would be equally suitable on a dark or light background, or even drawn directly over a bitmap/image.



I've deliberately only coded a few letters, to keep the size of the code down, so burning it to the mcu doesn't take forever each time I try out an update.
I have coded the entire font set (I wrote a custom VB app to do it for me) but the full font set bloats the PIC code from 3k to 12k - the burning time increases fourfold and while I'm still trying stuff out, I only need a few characters anyway. Implementing other characters means simply increasing a look-up table.

And now for the "reveal" - a working demo of the BlackoutX font on a QVGA LCD screen:



Ok, it's not quite there yet, but at least you can see readable characters on the display! There's a little bug in the code that draws the "transparent" pixels as black, which make the letters appear to be on a black background - so you don't get the full "outline" effect. But that shouldn't take long to hunt down and sort out....

0

Check this out!

Posted by Chris on Thursday, November 26, 2009
Result.
Success.
Call it what you will.



See that little blue square?
I drew that. It seems the LCD init routine was working all along - it just wasn't visible because of the backlight problem! Put 9V onto the backlight (check out the PP3 connected to the VIN pin at the top of the photo) and it all works perfectly.

So at least have a working solution for now, keeping the PP3 connected to make the LCD viewable. Obviously, in time, we need to be able to get the whole thing running from a single 3.3V source. But that's a problem for tomorrow. Today, we've got some graphics drawing libraries to build!

0

Getting the same results at last!

Posted by Chris on Thursday, November 26, 2009
It's been a despondent couple of days in Nerd Towers, trying to get the LCD display working from a PIC 18LF4550 (with USB support). First off, we had to step the supply voltage down from 5V (from the usb bus) to 3.3V via voltage regulator. This is to simulate running the screen and PIC from a lipo battery, not from the usb bus.

The problems started straight away.
Maplins Brighton didn't stock any 3V3 regulators. The web said "2 in stock" but at the store, they had none. Now, I don't mind admitting that Wrexham in North Wales is not the nicest place to live, but the Maplins store there is excellent. They stock pretty much anything you care to ask for over the components counter, and the staff and friendly and knowledgeable. Ask for a 470uF capacitor and they'll even ask if you're building a USB device (they take in interest in what their customers are using the components for) and give you a range to choose from - they're interested in what they sell and understand their customers.
The Brighton Maplins stock nothing. Two NPN transistors? What's the catalogue number? Sorry, we've only got one of those in stock. No I can't offer an alternative. You give me a catalogue number and I'll see if we've got it in stock (they invariably haven't!)

Anyway, enough about Maplins - a load of 3v3 regulators arrived in the post (ordered from the Farnell website, delivered next day) and we got to work. We made sure that we had the 18LF versions of microchips (the L being "low voltage") which run at anywhere between 2.5V and 5.5V.
Running off the 5V USB bus, the PICs worked fine (we always use an LED to show when the PIC is doing something, so as long as it's lit/flickering, we can tell that the PIC is actually doing something). But run a PIC18LF4550 from 3.3V and nothing happens. Zero. Zilch.

It turns out that PIC18s can't be relied on to support 20Mhz crystals at 3.3V - the datasheet shows a voltage/oscillation graph and 20Mhz is just out of the "safe zone" at 3V3. So we had to buy in some 16Mhz crystals (yes, you guessed it, none in stock at Maplins, Brighton). While waiting for them to arrive, I stuck some wires onto the crystal on Xing's Arduino board and used that (the Arduino uses a 16Mhz crystal - perhaps for the same reason?).

Still nothing.
What this time?
The brown-out fuse! Even with the brown-out voltage set to 2.1V the PIC refused to work. Disable the brown-out fuse, and the PIC magically comes to life and works perfectly with a 16Mhz crystal (albeit by this time, we'd reduced the code to a simple "turn-on-an-led" routine).

So now we had a PIC running at 16Mhz and at 3.3V. Brilliant.
Code it up with the LCD initialisation routines and off we go.....
Nothing.

Plug the LCD into the Arduino - it lights up and initialises perfectly.
So at least we know we've not damaged the LCD!
Plug the LCD into the PIC and there's nothing. Zero.
Testing the pins with a multimeter, comparing the two set-ups provided us with some interesting information. Namely, that when connected to the Arduino (see photo on this earlier post) the VIN pin has 9V on it. When connected to the PIC, this pin reads 0V.
Xing specifically said to connect 3.3V to the 5V supply pin and NOT to use the VIN pin (because of the way this prototype board is wired, the 5V supply on the Arduino does actually read 3.3V). So when connected to the PIC, the VIN pin is zero.
What happens if we bend this pin back, so it can't make a connection when the LCD is connected to the Arduino?
Hmmmm.
The LCD fails to light up. It just sits there. Dead.

Result! It may not be working, but at least we now get the same result using both PIC and Arduino controllers.

0

Now we're getting somewhere....

Posted by Chris on Tuesday, November 24, 2009
Back from holidays - ok, not all the nerds went away, but not everyone is quite as dedicated to filling the blog with drivel as some of us, so things were on hold for a while. But the good news is, we're back!

And the even better news is that the day after we got back, we'd already arranged a meeting with our old pal Xing from NuElectronics. And what better place to meet up and sort out LCDs, charge-pump capacitors and all things techie, than in a busy cafe on Clapham Junction Station, at the height of rush-hour? No, we couldn't think of one either, so that's where we met up!

It's always nice to meet up with people and put a face to name (not all us nerds are socially inept, though sometimes it does feel that way!) and in no time at all, two and a half hours had flown by. Xing had some really good ideas for putting our ScoreSure device into production, including having "kits" made up, consisting of enclosure, boards, batteries and so on, ready to be programmed and assembled. We also discussed using a bootloader and the pros and cons of allowing end users to install their own firmware updates, and talked at some length about the future of ScoreSure even though we've yet to build a final, working prototype! In short, it was a really interesting and exciting meeting, and he has given us a deadline to work towards - he's away visiting factories and suppliers in China in December, so we've got just a few short weeks to get something designed and built, ready for prototype manufacturing.

At the end of the meeting, he presented us with a working 320x240 QVGA LCD, mounted on an Arduino board. We'd sent him one of our displays, on our own breakout board to see if the problem we'd had was the hardware (dodgy soldering/etching) or the software in the PIC. He has taken our screen off the dodgy breakout board, and put it onto one of his kits just to make sure that it actually worked (he did say he couldn't find a fault on our board, but neither could he get it working with his set-up either). He even went to the trouble of loading example code into the Arduino to demonstrate it working with our dodgy screen:



So now we have, in our grubby little mitts, a working LCD board mounted on a breakout board, ready to interface with our own PIC microcontrollers. Just as soon as we've worked out which voltages go to which pins, I'm sure it won't be long before the SureScore logo makes and appearance on a full-colour QVGA display.......

0

En vacances

Posted by Chris on Thursday, November 19, 2009
Nous sommes en vacances.

1

Check out the working QVGA LCD!

Posted by Chris on Tuesday, November 17, 2009
Look at this beautiful image. A working QVGA LCD. Neat huh?
Look closely. Yes, it's a mirror image, but that's only due to a few flags not being set. That's easy to resolve.



Now look again. Imagine it was drawn the right way around. Testing blah blah... with an AVR. That's right. An AVR. Until now, we've worked exclusively with PICs.
In fact, we've an admission to make - that's not actually one of our screens that's working: it's one that Xing at NuElectronics got working and sent us photos to show that it is possible!

But we've got our hands on the correct datasheets this time (at least, the same ones he's been using, so they should be correct) so it shouldn't be too long before we're looking at our own bitmaps on these excellent little screens.....

0

Bit padding and byte stuffing

Posted by Chris on Saturday, November 14, 2009
Determined not to let the fact that the LCD still refuses to switch on stop us, we've been pretty busy over the last few days. Ok, the LCD just sits there, blank and lifeless. But one day it will flicker into life. And when it does, we need to be able to send data to it. So we'll just continue, unabashed, as if everything was working anyway.

So now we're looking at data storage and sending data to the LCD.
Our preferred method is through a 16-bit parallel data bus. The LCD typically uses 18-bit colours for the display, but internally can convert a 5-bit colour value into 6-bits for the red and blue channels (it simply copies the most significant bit into the least significant bit place).



This means that we need a piece of software that can take 24-bit images and convert them to 16-bit. That's easy enough. But we need to make sure that said software stores the data in R5-G6-B5 format. Hmmm. Not quite so easy.

Then we started to think about numbers - a 320x240 image takes up 76,800 bytes. Since we're using 16-bit colour values (i.e. two bytes per pixel) this means a whopping 153,600 bytes for a full screen image. Wow!
So we've opted to use "palletized" images - a bit like GIFs: create a palette of 256 colours, then use a single-byte-per-pixel to point to the palette index. This will keep full-screen images down to *just* 76,800 bytes (plus 512 bytes for the palette).
Storing such an image in Flash memory means taking up about 302 "pages" of data (one page = 256 bytes). And our 4Mbit memory chip has 2,048 pages, so each full-screen image will take up just under 15% of the available memory! It's probably best to keep the number of full screen bitmaps down to a minimum!

We've discussed sprite/tile-based approaches and will investigate these further, but for now, we're concentrating on storing and displaying a full-screen image, in R5-G6-B5 format. So here we go:

Each pixel in the source image is interrogated and it's full colour (24-bit) value is retrieved. This colour value is split into its red, green and blue components (we use the fantastic Freeimage DLL for all our image manipulation tasks.)

Each red, green and blue element of the pixel colour is a single byte (8-bits).
We want a 5-bit value for red, a 6-bit value for green and a five-bit value for blue. To achieve this, we simply bit-shift the red value RIGHT three times (the same can be achieved by dividing by 2, three times, ignoring any remainder values). So a red value of, for example, 186 is binary 10111010. We can see visually that bit-shifting this three positions to the right should give us xxx10111.
Divide by two, three times (or divide by 2^3 = 8) and we get:
186 / 2 = 93
93 / 2 = 46 (ignore the 0.5)
46 / 2 = 23.

The binary representation of 23 is 10111. Perfect!
(if you're not confident with decimal to binary conversions, a quick Google search should get you started, or try this link.)

We repeat this process for the blue element (bit-shift right three places)
For green, for only need to bit-shift two places right (or divide by 4) since we want to keep 6 bits for the green channel. (Why six? Because the LCD specification says a 16-bit interface is mapped to a R5-G6-B5 colour value).

If you look closely at the RGB breakdown (above), you'll also see that the green 6-bit value is split over the two bytes. Bugger.
So we need the 5-bit red value to occupy the upper 5 bits of the first byte, followed by the upper three bits of the green colour. Now listen up, this is where it gets tricky: We want the lower three bits of the green colour to occupy the upper three bits of the second byte. Then the five bits that make up the blue colour to occupy the lower five bits of the second byte. Got that?

Here's what we do:
Bit shift LEFT the red colour value, three times
(yes, we could have just used bit-masking earlier, but I'm trying explain a process here, so bear with it!). To shift right, we divide by 2. It makes sense that to bit-shift left we multiply by two:

The red value xxx10111 becomes 10111000

Let's say we have a green value 42, binary xx101010
We want the first three bits to take the place of the last three zeros in the red colour value. How do we do this? As before, bit-shift right, three-times.
Our green value xx101010 becomes xxxxx101
Now simply add this value to the red value.
For bit-wizards, you can perform an OR operation on the two binary values, the result is the same:

10111000 OR 00000101 = 10111101
184 + 5 = 189
10111101 = 189. Perfect!

The easiest way to get the last three bits of the green value is to use bit-masking.
Simply put, bit-masking compares two values, on a binary level, and where two bits are both set, the resulting bit is set (value=1) otherwise is not set (value=zero).
Here's an example:

1011 AND 01110

first bit of first value: 1, first bit of second value: 0, result = 0
second bit of first value: 0, second bit of second value: 1, result = 0
third bit of first value: 1, third bit of second value: 1, result = 1
fourth bit of first value: 1, fourth bit of second value: 0, result = 0

So 1001 AND 01110 = 0010

If we want to recover just the last three bits of a value, we create a "mask" made up of the bits we want to keep. You might even call it a "bit-mask". The bitmask for the last three digits is 00000111

So, back to our RGB colours - we want the last three bits of the original green value 42, binary xx101010:

00101010 AND 00000111 = 00000010

The first three bits (the ones we're interested in) are: xxxxx010
But we need these three bits to be the first three bits in the second byte value.
This means, as before, bit-shifting LEFT, five-times (multiply by 2, five times- or multiply by 32)

We can see that bit-shifting the value left should give us 01000000
By a happy coincidence, the original value 010 = 2
2 x 2^5 = 64
The binary representation of 64 is 01000000. Perfect!

So we now have the lower three bits of our original green value in the upper three bits of the second byte. All that remains to do is add in the blue bits. As before, a bitwise OR statement would achieve this - or we could simply add the blue value to this new second byte value.

Let's say our blue value is 11, binary 01011.
01000000 OR xxx01011 = 01001011
64 + 11 = 75
75 in binary = 01001011

Right. That's one 24-bit pixel stuffed into a 16-bit (2-byte) value.
Only 76,799 more to go!

0

Connecting to a QVGA LCD

Posted by Chris on Thursday, November 12, 2009
Well yesterday morning a parcel arrived containing one of these little photo frame jobbies. We plugged it in and tried it out - very nice. The image quality is great (though the refresh rate looked a little disappointing - you could visibly see the screen updating, and it took 1-2 seconds to draw an entire full-screen image).
No matter, what we needed to do was crack the thing open and get stuck in, just like Xing had done with his, in order to send us these photos.

Once it was open, the first thing to do was to get the LCD ribbon off the PCB.
This was actually easier than first anticipated, following the sage advice of Robot Steve. Simply put, we followed his diagram and heated the solder connecting the pins to the ribbon, by heating *behind* the ribbon connector - applying the iron to the connections on the PCB, not the ribbon itself.



By starting at one end, and with a wide chisel-tip on the iron (wide enough to heat four pins at a time) we could reflow the solder and gently lift the ribbon clean off the PCB. It came of quickly and easily with no broken pins, traces or connectors. Brilliant!

We then laid the ribbon across our own PCB breakout board.... and found we'd made our traces too small. The ribbon was far too wide. Bugger. That meant we had to make up a new PCB (not actually a bad thing, since our earlier effort had a few broken traces anyway). An hour or so later and we'd managed to etch a couple of new breakout boards (its always worth having one spare, just in case). This time, the traces on the PCB and the connectors on the LCD ribbon lined up perfectly.

The ribbon was connected by using the same wide chisel-tip, and running the iron quickly across the top of the ribbon, flowing the solder onto the homemade PCB breakout board. Luckily there was enough solder left on the ribbon to connect pins to our PCB.



The last thing to do was connect the pin headers to the 2 x strips of 18-holes and see if we could get the thing to switch on. That's where we're up to now (it was a late one last night, getting the ribbon connected onto the PCB). Although we don't know the initialisation sequence, at this stage, it'd just be nice to see a backlight or something come on, if only to show we haven't made a mess of soldering the ribbon cable to the PCB board!

We've checked and double-checked all the pins for continuity, and checked that there are no shorts across the pins (they're tiny little traces in case you hadn't noticed!) so in theory it should work first time.........

0

320x240 QVGA LCDs

Posted by Chris on Tuesday, November 10, 2009
Here's a picture of a K838 digital photo frame, cracked open:


It basically consists of:
An AX203 microcontroller
A 2.4" LCD (320x240 pixels, QVGA, 65l colours)
Flash memory
Battery charging/protection circuit
USB plug/socket
A few crystals (one for driving the USB, one for the real-time-clock RTC)



We found similar LCD screens (the screen only, not in a nice enclosure) on eBay for about £12 each, so ordered a couple to have a play with - they may or may not use the same LCD driver chip; we'll soon find out! The LCDs on eBay also have an ingenious method of connecting the ribbon cable to the printed PCB - each exposed pin on the ribbon has a hole drilled through it. So when solder is applied to the top of the pin, a tiny dot can pass through, welding it to the PCB underneath.



Because we like working with big, fat, 0.1" breadboards and soldering to huge great big pads, we decided to have a go at building an LCD-to-DIP connector. Rather that a single line of pins, we built a double-inline-pin connector, because the LCD has no less than 36 pins to interface with. (Putting them into a two lines just seemed easier!). Bouyed by the brilliant comments on an earlier SMT project we figured that soldering to a tiny ribbon connector would be - if not easy - at least possible.



The etching on this one went a little awry. Actually, it's not as bad as it could be and the camera doesn't do the etching of the tiny fine traces justice. Although they appear blurred and merged together on the photo (highlighted on the left) each individual trace for the LCD ribbon is properly formed and complete. We should really have checked the traces leading back to the pins before etching, however, because - highlighted on the right - the connection to one of the pins has completed etched through. We'll have to patch this with a bit of silver paint or similar before testing...

0

Count Arthur Who?

Posted by Chris on Monday, November 09, 2009
"Oh, sod it? Which dozy idiot is ringing my bell now?"
If you're not familiar with the ramblings of Count Arthur Strong, you'd do well to tune into Radio4 every now and again for the Count Arthur Strong Radio Show. Yes, Radio4 - that'll sort the uber-nerds from the, erm, wheat-chaff thing. Although, if you're still in nerd-denial, you could always keep some dignity and tune in to Radio7 and catch some of the earlier shows when they are repeated.

Then again, you could always get some tickets and see the man himself performing live. If you're really lucky (as a few of us were last night) you might even get them for free (the BBC does not charge for tickets to see shows that are being recorded for television or radio).

If you like your comedy peppered with "malapropisms, spoonerisms, tall stories and archive footage meticulously stitched together… " as the Mail on Sunday would say (that's a quote lifted from the Count Arthur Strong website, not something that any of us would admit to reading) get yourself along to one of his live shows! Not only do you get the chance to hear yourself coughing/sneezing/farting from in the audience when the show is broadcast on the radio, but you also get to hear the outtakes, re-takes and general mucking about that goes on when things don't quite work out the first time around.
It's suitable for all the family, and you won't be embarrassed if you want to take along your 90-year-old Aunt Maud, nor do you need to worry about the kids picking up bad language either.

For a preview, check out the Radio4 website when no-one is looking.
If you're after BBC (i.e. free) tickets, get in there quick. The Count Arthur fan-base is growing quickly and already has a few new members after last night.

1

Reading PWM signals

Posted by Chris on Sunday, November 08, 2009
While waiting for the screens and samples for developing ScoreSure v2.0 I've been looking at a little project for Tom from RobotBrighton. He builds "battle robots" and has developed a relay-driven controller board for one of his 'bots (he has a habit of letting smoke out of his components and says he's burnt through quite a few MOSFETs already!).

The idea is to take RC (remote control) signals and convert them to on/off switching signals. RC signals work in a similar fashion to driving servo motors. A signal with a pulse width of x milliseconds is decoded at the other end to determine how far a joystick has been pushed on a remote control handset.

For this project, there are a few rules that have to be put into place as well as basic pwm-decoding: firstly, the signal width MUST be between 0.5ms-2ms. Any signal outside of this range should result in the controller sending an "error" signal, or putting the controlled device into a 5 second delay/standby mode.
Also, pulse widths for servo controls are often repeated at 2.5m/s intervals, although this may or may not be the case for the RC controller. So we need to measure the width of a signal coming in and act on it accordingly, but not necessarily worry about the frequency of the signals as these may be subject to fluctuation - i.e. we cannot assume that all signals start exactly 2.5ms apart.

To achieve this, we're going to use a humble 16F628A PIC chip.
It's cheap and available (but to be honest, for something relatively simple like this, it's a bit of overkill: a smaller/cheaper PIC could be used, but we've got quite a few of these hanging about, so we'll use one of these instead).
In order to accurately detect when a signal starts and ends, we're going to use the PICs interrupt routines. A PIC chip can generate interrupts in a number of scenarios. We're going to generate an interrupt on every change of input on pin RB4.



We also need to make use of a 16-bit timer and some pre-scaling, to calculate the width of each incoming signal pulse. Whenever pin RB4 goes high, an interrupt occurs and at this point the timer is reset to zero. We will also make use of the CCP module to generate an interrupt whenever the timer has counted the equivalent of 2 milliseconds. This will form the basis of our fail-safe.

So now, whenever an interrupt occurs we need to look at the state of the RB4 pin and the interrupt source to decide from which of the following three sources the interrupt came:

a) RB4 just went from low to high (we need to reset the timer)
b) RB4 just went from high to low (we need to read the timer to calculate the pulse width)
c) The CCP module is telling us that more than 2ms have elapsed since the start of the pulse (i.e. pwm value is outside the valid range)

By using these two interrupt sources, we do not need to worry about the frequency of the pulses, or about matching the timing of them. Whenever an invalid pulse width is read, the PIC goes into "standby" or error mode for a period of time, but when it comes out of that state, it can simply pick up on the next pulse that comes in - we don't have to worry about the PIC starting reading pulses from the wrong place in time (an effect referred to a phase-shift).

By following this approach, we should be able to read the value of the timer, whenever pin RB4 goes from high to low, and calculate the width of the pulse that generated the interrupt. If the pulse width is too short, we should put the PIC into a standby/error state. If the pulse width is too long, it will generate it's own error interrupt and will be handled accordingly. Any other value for the timer means we can see if it has passed a specific threshold value and toggle the on/off pin as necessary.

An alternative approach would be to poll the input pin(s) continuously, setting and resetting the internal timer as the pin state changed from high-to-low and back again. We may also explore this approach and compare the two.

0

Interfacing with Flash memory

Posted by Chris on Wednesday, November 04, 2009
Ok, here it is. Some Oshonsoft PIC Basic code for reading and writing data to a Flash memory device.
This example writes data through the Flash internal buffer(s) and reads/writes data one entire page (256 bytes) at a time. Because of the limitations of the USB implementation, the PIC keeps a mirror copy of the Flash buffer in memory and when called for, sends a group of 8 bytes to the USB host device.
This code example works with a PIC and Flash memory connected according to the schematic from this post, with the Flash memory connected to pins PORTA.0-3


Define CLOCK_FREQUENCY = 20
Define CONFIG1L = 0x24
Define CONFIG1H = 0x0c
Define CONFIG2L = 0x3e
Define CONFIG2H = 0x00
Define CONFIG3L = 0x00
Define CONFIG3H = 0x05 '0x83
Define CONFIG4L = 0x80
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40

'SPI setup
Define SPI_CS_REG = PORTA
Define SPI_CS_BIT = 1
Define SPI_SCK_REG = PORTA
Define SPI_SCK_BIT = 2
Define SPI_SDI_REG = PORTA
Define SPI_SDI_BIT = 3
Define SPI_SDO_REG = PORTA
Define SPI_SDO_BIT = 0
SPIPrepare

'USB setup
UsbSetVendorId 0x099
UsbSetProductId 0x004
UsbSetVersionNumber 0x1001
UsbSetManufacturerString "ScoreSure"
UsbSetProductString "ScoreSure Template Device"
UsbSetSerialNumberString "0123456789"
UsbOnIoInGosub usbonioin
UsbOnIoOutGosub usbonioout
UsbOnFtInGosub usbonftin
UsbOnFtOutGosub usbonftout
AllDigital

'general declarations
Dim i As Byte
Dim j As Byte
Dim state As Byte
Dim iusb As Byte

'memory access variables
Dim addri As Byte
Dim addrj As Byte
Dim addrk As Byte
Dim ai As Byte
Dim bi As Byte
Dim ci As Byte
Dim useusb As Bit
Dim pageaddr As Word
Dim byteaddr As Byte
Dim bytecount As Word
Dim picbuffer(256) As Byte
Dim picbufferpointer As Byte
Dim flashstatus As Byte

'initialisation
init:
  useusb = 1
  picbufferpointer = 0

'startup
start:
  If useusb = 1 Then UsbStart


'main loop
loop:
  If useusb = 1 Then
    UsbService
  Else
    Select Case state

    EndSelect
  Endif

Goto loop
End

usbonftout:
  'feature reports.
Return

usbonftin:
  'don't do anything on feature.
Return

usbonioout:

  'received data from host into PIC
  'Here we put a single command byte into buffer(7) to tell the PIC
  'what we want it to do.

  Select Case UsbIoBuffer(7)

    '---------200+ are memory control commands --------

    '-----------------------------------------------------------
    Case 200 'set page address 0-2048 (byte 2= MSB, byte 1=LSB)
    '-----------------------------------------------------------
    iusb = UsbIoBuffer(2)
    pageaddr = iusb * 256
    iusb = UsbIoBuffer(1)
    pageaddr = pageaddr + iusb

    '-----------------------------------------------------------
    Case 201 'set byte address within a page (1 page=256 bytes)
    '-----------------------------------------------------------
    byteaddr = UsbIoBuffer(2)

    '---------------------------------------------------------
    Case 202 'load flash memory page into flash memory buffer
    '---------------------------------------------------------
    Gosub flashmemorytoflashbuffer

    '--------------------------------------------------------------
    Case 203 'load flash memory buffer (256 bytes) into PIC buffer
    '--------------------------------------------------------------
    Gosub flashbuffertopicbuffer

    '-------------------------------------------
    Case 204 'write PIC buffer to memory buffer
    '-------------------------------------------
    Gosub picbuffertoflashbuffer

    '-------------------------------------------
    Case 205 'flash buffer to flash page memory
    '-------------------------------------------
    Gosub flashbuffertoflashmemory

    '---------------------------------------
    Case 206 'set picbuffer pointer (0-255)
    '---------------------------------------
    picbufferpointer = UsbIoBuffer(6)

    '------------------------------------------------
    Case 207 'load 4 bytes from host into pic buffer
    '------------------------------------------------
    For iusb = 0 To 3
      picbuffer(picbufferpointer) = UsbIoBuffer(iusb)
      picbufferpointer = picbufferpointer + 1
    Next iusb

    '---------------------------
    Case 208 'start stream read
    '---------------------------
    streamread = 1
    SPICSOn
    SPISend 0xe8 'stream read (legacy mode)
    SPISend pageaddr.HB
    SPISend pageaddr.LB
    SPISend byteaddr
    SPISend 0x00 'four don't care bytes
    SPISend 0x00
    SPISend 0x00
    SPISend 0x00

    '-------------------------
    Case 209 'end stream read
    '-------------------------
    SPICSOff

    '--------------------------
    Case 210 'empty PIC buffer
    '--------------------------
    Gosub emptypicbuffer
    picbufferpointer = 0

    '-------------------------------------------------
    Case 240 'clear entire memory (use with caution!)
    '-------------------------------------------------

    '-------------------------------------------
    Case 253 'flash memory status register read
    '-------------------------------------------
    Gosub getflashstatus
    Gosub emptypicbuffer
    picbuffer(0) = flashstatus

    '-------------------------------------------------------------------
    Case 254 'blow the fuse on the flash memory to set to 256-byte mode
    '-------------------------------------------------------------------
    SPICSOn
    SPISend 0x3d
    SPISend 0x2a
    SPISend 0x80
    SPISend 0xa6
    SPICSOff

  EndSelect
Return

usbonioin:
  'send data from PIC to host
  'if you use a loop in here, garbage gets sent back!

  If streamread = 1 Then
    'load the data from flash memory (direct access, legacy mode)
    'straight into the usbiobuffer
    SPIReceive UsbIoBuffer(0)
    SPIReceive UsbIoBuffer(1)
    SPIReceive UsbIoBuffer(2)
    SPIReceive UsbIoBuffer(3)
    SPIReceive UsbIoBuffer(4)
    SPIReceive UsbIoBuffer(5)
    SPIReceive UsbIoBuffer(6)
    SPIReceive UsbIoBuffer(7)

  Else
    iusb = picbufferpointer
    UsbIoBuffer(0) = picbuffer(iusb)
    iusb = iusb + 1
    UsbIoBuffer(1) = picbuffer(iusb)
    iusb = iusb + 1
    UsbIoBuffer(2) = picbuffer(iusb)
    iusb = iusb + 1
    UsbIoBuffer(3) = picbuffer(iusb)
    iusb = iusb + 1
    UsbIoBuffer(4) = picbuffer(iusb)
    iusb = iusb + 1
    UsbIoBuffer(5) = picbuffer(iusb)
    iusb = iusb + 1
    UsbIoBuffer(6) = picbuffer(iusb)
    iusb = iusb + 1
    UsbIoBuffer(7) = picbuffer(iusb)

  Endif
Return

setflashdeepsleep:
  'when we're not using the flash memory, set it to deep sleep which causes it to
  'use minimum amount of power (it's basically on super-standby) opcode B9H
  SPICSOn
  SPISend 0xb9
  SPICSOff
Return

setflashwakeup:
  'when we've put the flash memory into deep sleep, it ignores all commands sent to
  'it until it's been woken up by sending opcode ABH
  SPICSOn
  SPISend 0x0ab
  SPICSOff
Return

flashmemorytoflashbuffer:
  SPICSOn
  SPISend 0x53 'transfer memory page to buffer1 command
  SPISend pageaddr.HB 'send the page address to read data
  SPISend pageaddr.LB 'from into buffer number one
  SPISend 0x00 'don't care 8-bits
  SPICSOff
Return

flashbuffertoflashmemory:
  SPICSOn
  SPISend 0x83 'transfer buffer1 to flash page (with built-in erase) command
  SPISend pageaddr.HB 'send the page address to read data
  SPISend pageaddr.LB 'from into buffer number one
  SPISend 0x00 'don't care 8-bits
  SPICSOff
Return

flashbuffertopicbuffer:
  SPICSOn
  SPISend 0xd4 'buffer1 read command
  SPISend 0x00 'start off with 16
  SPISend 0x00 'don't care bits
  SPISend 0x00 'then buffer byte to start reading from (always zero)

  For picbufferpointer = 0 To 255
    SPIReceive picbuffer(picbufferpointer)
  Next picbufferpointer
  picbufferpointer = 0
  SPICSOff
Return

picbuffertoflashbuffer:
  SPICSOn
  SPISend 0x84 'buffer1 write command
  SPISend 0x00 'start with 16
  SPISend 0x00 'don't care bits
  SPISend 0x00 'then buffer byte to start reading to (always zero)

  For picbufferpointer = 0 To 255
    SPISend picbuffer(picbufferpointer)
  Next picbufferpointer
  picbufferpointer = 0
  SPICSOff
Return

emptypicbuffer:
  For i = 0 To 255
    picbuffer(i) = 0
  Next i
Return

getflashstatus:
  SPICSOn
  SPISend 0xd7 'status register command
  SPIReceive flashstatus
  SPICSOff
Return


The first thing to do, once connected and the USB device recognised, is to set the page size to 256 bytes. This is done by sending the byte command (from PC to PIC)
number 254. Before doing this, we checked the Flash memory status register:
Send (from PC to PIC) byte command 253. This is done by clearing the entire USB buffer - setting all values to zero - on the PC then setting USB byte(7) to 253 using the VB command:
data(0)=0
data(1)=0
data(2)=0
data(3)=0
data(4)=0
data(5)=0
data(6)=0
data(7)=253
HIDTerminal1.HIDSendReport(data(0), data(1), data(2), data(3), data(4), data(5), data(6), data(7))

(see Oshonsoft PIC18 USB section for details about communicating with your PIC-based USB device from your PC and the HIDTerminal Activex control which encapsulates USB functionality.

After the byte command 253 has been sent to the USB device, the internal PIC memory buffer should be blank (all zeros) except for byte(0) which contains the Flash Status Register value. We read this back to the PC by issuing the VB command:
HIDTerminal1.HIDReadReport(data(0), data(1), data(2), data(3), data(4), data(5), data(6), data(7))

Displaying the values for data(0-7) on screen (we use a few text boxes, but you could use Debug.Print or any other method to view the values) we see that the Flash Status Register value is 156 or, in binary:
10011100

Checking the AT45DB041D datasheet we can see that the last bit of the status register (bit zero) tells us whether each page size is 264 (default) or 256.
In this case, we can see - because it's a brand new device - bit zero is cleared, which signifies that a page size is set to the default of size 264 bytes.
We issued the "change page size" command from PC to PIC (which in turn sent the byte sequence 0x3D, 0x2A, 0x80, 0xA6 to the Flash memory) to blow the fuse holding the page size value - effectively turning it to a 256-byte page size. This is a one-time operation and cannot be undone.
After repeating the "read Flash Status Register" routine as outlined above, we now got a status value of 157. This tells us that bit zero of the Flash Status Register is now set, which - according to the datasheet - signifies that the Flash unit is now working with a 256-byte page size. Just the result we were after!

Using a combination of send and read commands, we are now able to read and write data to and from the Flash memory device.
Result!

whos.amung.us

Copyright © 2009 .Nerd Club All rights reserved. Theme by Laptop Geek. | Bloggerized by FalconHive Supported by Blogger Templates.