dgHacks https://www.dghacks.com Microcontrollers, Electronics and other interesting stuff Fri, 11 May 2018 14:30:36 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.26 How does a Smart DNS Proxy Unblock Geo Restricted Sites https://www.dghacks.com/kodi/smart-dns-proxy/ https://www.dghacks.com/kodi/smart-dns-proxy/#respond Fri, 11 May 2018 14:29:03 +0000 https://www.dghacks.com/?p=166 You click on your favourite movie viewing site and are surprised to see a message which says that this video is not available in your area.
The other possibility is that you arrive on their site but cannot find that amazing movie that everyone has been raving about.
Even more frustrating is those people all got it from this content provider. Without you realizing it, they have diverted you to
their designated site for your country which only contains a limited list of movies.

After a bit of internet searching about geo unblocking you come across two possibilities.
VPN and Smart DNS proxy. After some more searching you think you have an understanding of how a VPN works
but due to a lot of misleading sales talk your understanding of the Smart DNS proxy might be a little less clear.

So lets take a quick look at how they work.

The VPN (Virtual Private Network)

You run some VPN application on your device. You give the application the addresses of the VPN servers you are using.
You start a connection to a VPN server. From this moment on all internet traffic from your device is encrypted by the application before being sent to the VPN server.
You connect to the content providers web server.  and do what is required to download the movie you want to watch.
On the other end of the VPN tunnel, the server un-encrypts your data. It then finds the packet return address (your ip address) and changes it to the ip address of the VPN server.
This last step is very important because it prevents the content provider from figuring out who you are and where you are.
The content providers web server has been fooled by the VPN server into thinking you are in its local location. It now redirects you to the actual movie file / stream.
Most content providers use external CDN (Content Delivery Network) services or separate file servers to deliver Movies or other content.
The VPN server does all the communicating with the content provider including connecting to the CDN server and getting the movie which it encrypts and sends back to your device.
Your device un-encrypts it and you sit back and watch your movie like those people on the other side of the planet.

DNS Server

To understand how the Smart DNS proxy works we first need to understand how a normal DNS server works.
DNS servers do more than what is illustrated here, but this is close enough for this discussion.

Standard DNS server.

All devices on the internet are addressed using IP addresses but it is easier to remember www.google.com than something like 66.102.15.255.
Ok so lets watch our movie. We enter our content providers URL in our browser and press enter. Our device contacts a local DNS server to ask it for an IP address that is linked to that URL.
If the local DNS already has the IP for this URL it will return it. If the IP is unknown it will make a request to a Root DNS server which will usualy request this information from a TLD DNS server. The TLD server will have knowledge of other DNS servers within the TLD (Top Level Domain. eg .com .uk)and return their address. The DNS server at the final leg of the journey will  return an IP address of the server that you want to reach, back to your device. Your device now uses that IP address to connect to the content providers web server.
The content providers web server examines your IP address and at some stage gives you the bad news that you are not welcome. Alternatively it might show you a limited list of movies that it allows for your location.

Smart DNS Proxy

The Smart DNS proxy provider gives us the address of their Smart DNS server which sends us to their DNS proxy . We tell our device to uses this server instead of the usual DNS server.
This can also be done by means of an application running on our device.
Ok so lets watch our movie now.
We enter our content providers URL in our browser and press enter.  Our device contacts the Smart DNS server and gives it the content providers URL and waits for the returning IP address.
The Smart DNS detects that this URL is one that is in its list which it can unblock. It sends us the IP address of  a Proxy server. Our browser thinks this is the IP of the content provider and makes a standard web connection .
In a similar fashion to the VPN server, the proxy server replaces our packet return IP address with its own IP address. It then forwards the packet to the content provider. The content providers server is fooled by the proxy server into thinking the request is coming from its local area. The content providers web server now redirects us to the server hosting the movie. At this stage the Smart DNS detects that this address is no longer a URL which requires IP changing so it sends us the IP of the file server.
Our browser makes a direct connection with the file server and we happily watch our movie.

The pros and Cons.

For the VPN / Smart DNS provider.

To provide either the VPN or Smart DNS proxy a bunch of IP addresses are required. The more subscribers using the service the more IP addresses are required.
If a provider uses too few IP addresses then the content provider will see perhaps a thousand connections all coming from one address. It will know this is not a normal household connecting and the IP address will be blacklisted.

Encrypting and streaming lots of videos on a VPN server uses a lot of processing power. Many subscribers equal many VPN servers required to handle the load = exspensive for service provider.
Only a limited amount of traffic is sent through a Smart proxy so it will require a smaller number of servers = more cost effective for service provider.

For you the user.

All the encrypting and un encrypting by a VPN service can slow things down especially if the provider is skimping on buying enough servers.
VPN keeps you 100% anonymous from end to end.
VPN prevents your ISP / government from tracking what you are doing.

Smart DNS proxy is quicker but all the data travels in plain site.
Your IP address can be detected by the content providers file server / CDN provider.

Conclusion.

For just watching movies the best choice is using smart dns.

If you are in a country where the government censors/monitors what you do on the internet, then a VPN is most likely a better option.

 

]]>
https://www.dghacks.com/kodi/smart-dns-proxy/feed/ 0
Set up a VPN using the User Defined setting in Kodi VPN Manager Addon https://www.dghacks.com/kodi/customvpn/ https://www.dghacks.com/kodi/customvpn/#respond Sun, 22 Apr 2018 10:34:21 +0000 http://www.dghacks.com/?p=111 How to use the VPN Manager addon in Kodi to configure a VPN that is not in the managers list of options.
To connect to a VPN we are going to use the OpenVPN client.
This example is for Kodi running on a Raspberry PI but it will be similar for many other systems.
LibreElec, Openelec and other platforms already have OpenVPN installed. But to actually use OpenVPN you need to install the client add-on.
I have chosen to use CactusVPN for this example. The Kodi VPN Manager does not offer CactusVPN as one of the pre-defined options, so this will be a guide on how to get it up and running.
CactusVPN support 6 different protocols. This means that you will be able to get it working with almost all devices. Most importantly for us is they support the OpenVpn protocol which is exactly what we need for Kodi.
First we need to download a repository which has the OpenVpnManager in it.
Follow these simple steps.

Using your PC download the Zomboided repository

Get Repository Here

Save this file to a USB memory stick

Now for the OpenVPN config files.

Head over to CactusVPN and sign up. If you first want to make sure it works for you then sign up for their free trial, no payment required.
Once you have registered go into the client area and select ‘How To Start’ from the menu.
Look for the User name and Password near the bottom of the screen and make a note of them.

You will find the OpenVPN config files near the bottom of the page. OpenVPN config files for CactusVPN

Choose FreeVPN Trial or if you signed up choose from the other options.
Save these files on the USB memory stick.

Load it into Kodi

Plug the memory stick into the Raspberry USB port.
Go to File Manager and choose Add Source

img0 img02  img01

You should see the USB memory as one of the options. Choose it and give it name then click OK.

Exit from File Manager and choose Addons from the menu on left. At the top of screen click on

Install Repository

img1  then choose Install From Zip File img2

Find your USB memory in the list and find the repository file. img03

Install Addon

Once this is complete select Install from Repository in the same menu. Choose the Zomboid Add on Repository. img04

Click on Services then select VPN Manager for OpenVPN.

After the installation Click on Program Addons and you should see  the VPN Manager.

img06

Configure VPN Manager

Click on it  and select settings.  Choose User Defined from the VPN provider list. Also Set your User name and Password which you got from CatusVPN.

imgc1 imgc2

Scroll down and select the User Defined Import Wizard. imgc3

Select Yes when it asks to delete existing definitions.  On the next screen choose directory.

imgc4 then No on this screen    imgc5

Browse to the memory stick and select the folder which has the OpenVPN files which you downloaded from CactusVPN , Click OK.

Make a Connection

Now just one more step to configure it.  Choose VPN Connections from the left menu. Select First VPN Connection.

imgc6

If all is working you should see a list of server names.    sc2a

Pick a server and select OK. This might take a minute… s4

When it has completed click OK. Configuration over.

Click on the VPN Manager addon, select the Change or Disconnect VPN Connection option.

 

ss1

 

Sit Back and Watch a Movie

This is where you switch between VPN servers.

That’s it. There are many other settings but for now this will be enough to get you up and running.

 

Kodi, OpenVPN  and CactusVPN names are owned by their respective copyright holders.
]]>
https://www.dghacks.com/kodi/customvpn/feed/ 0
Using mechanical quadrature encoders in your project https://www.dghacks.com/micro-controller/quadrature_encoders/ https://www.dghacks.com/micro-controller/quadrature_encoders/#respond Sat, 20 Jan 2018 12:48:18 +0000 http://www.dghacks.com/?p=14 When I received the request to develop a down hill bike racing timer I thought that the Atmel Xmega would be the right tool for the job.
The system would need a 4 line LCD display with an easy to use menu system. The Xmega has a built-in Quadrature decoding feature, this influenced my decision to not only use buttons but also to include a quadrature encoder to allow for easy scrolling through menus and settings.
It sounded perfect. I decided to use the Alps EC12E24204A7 24 pulse encoder.

For those not familiar with a quadrature encoder lets take a quick look at what it looks like and what it does.
This decoder has 3 pins. One which is the common and 2 for the signals. It does not have an index pin. The index is so that you know when it has completed a revolution. We can do this in software.
From the outside it looks like a potentiometer:

encoder

Internally it is just two switches that open and close in a specific relationship to each other.
The pins in my circuit are connected as shown below. Take note that this means that when the switch is closed the output will be 0 and will be a 1 when open

encoderconnection

I used 4k7 resistors to pull the output up when the switch opens. This diagram shows the output of the encoder . The signals are 90 degrees apart.

encoderwav
What is really important here is that this pattern will reverse if the knob is turned the opposite direction.
This allows us to see which direction the knob is being turned.
Turned clockwise we will get the signal shown above…  02310231  turned anticlockwise we will get 13201320 assuming that A is bit 0 of the port and B is bit 1.
If you connect A to bit 1 of the port and B to bit 0 the sequence will be the same but the direction of it will swap.

The build

I set about creating schematics and doing the PCB layout. I used Kicad for this part of the build.

I sent the Gerber files to the PCB manufacturer and within a week I had PCB’s that required assembly.

Within a few hours and I had assembled a working prototype.

EncoderInUse  protoPCB1

After studying the Atmel application notes about the quadrature decoder I began writing the code. The built-in decoder makes use of the Xmega’s event system. The advantage of using events is that they only need  configuration, at run time they have no impact on the code running.
I was soon to discover that there is also a disadvantage to using the event system, but more about that later.
I was so confident that this was the solution that I went ahead and wrote the code required for the LCD and Menu system. From a user perspective the operation would be simple.
Turn the knob of the encoder and the menu would scroll up or down. Press the enter button and the chosen menu item would be selected. Press cancel to abort or go back a level.

It does not work as advertised

I loaded the code into the Xmega and after fixing a couple of minor issues to get the LCD running I was ready to test the menu scrolling. I turned the knob and the menu jumped around erratically. Sometimes if you just touched the knob the menu would scroll and jump all over the place. This was not the result that I had expected.
The application notes made it all sound so simple. After double checking my code I started to question the encoder itself. I looked at the single page that has the data for most of the Alps encoders.

The first thing that I noticed was the position of the detent stability point. This is the position of the ‘click’ as you turn the knob. Looking at their diagram you can see right away that the slightest touch on the knob will cause the B signal to change between On and Off.

encoderdata

 

The second thing was the chatter and bounce. This is electrical noise where the switch is fluctuating between on and off as the state changes.
The data sheet shows times of 3ms for chatter and 2ms for bounce

 

encoderchatter

I connected the encoder to an oscilloscope and checked if the figures were correct on the real part being used.
These two images of the B signal show that things in the real world are not always as pretty as those in the theoretical world

osc2 Osc1

The measurements show that they are within the manufacturers specifications but are not at all what the Xmega is expecting.
After digging around in the Xmega data sheet I confirmed that it has a digital filter which can be set up on the event pins.
The problem with this filter is that it can only be set to a maximum of 8 samples. Each sample is one clock cycle.
This means that on the 32Mhz clock which I am using the greatest width signal it can filter out is 250ns  This is far too short for the noise we see here.
So the question is why do Atmel make a chip that cannot decode real world devices? The answer is simple. This encoder is a relatively cheap mechanical encoder.
It costs about $1.00  If you are prepared to spend about $32.00 you can get an optical encoder such as the Bourns ENA1J-B28-L00025L  or if you are really feeling flush and want an encoder that does 600 pulses per revolution there is the Omron E6D-CWZ2C 6000P/R which is about $4830.00
These do not have the problems that a cheap mechanical encoder does and are most likely what Atmel had in mind with the Xmega.
Of course you can always use external components to sort out the noise problems but that kind of defeats the object of this exercise.

Not all good

Earlier I spoke about the downside of the Xmega’s event system. Because there is no code running, there is no way that we can change the way the decoder works. It is done by hardware not software. We simply configure the event and the Xmega does the rest and gives us the count and direction in registers. After trying various hacks to get it sorted out I decided that it was time to write my own routine. At first I looked at what was available on the internet. Many were either very simple bits of code that had clearly never been tested in practice, or only detected a single change count for each 4 part step. I wanted something that would count for each and every step and not be prone to errors.

Role our own

Thinking about the problem, we need to be able to filter out the noise. It is not only the noise. We also have the detent right on a switching point which causes the B output to switch even when not turning the knob. We therefore want  to ignore any signals that are not part of the expected sequence. So if we are expecting 02310231 but instead get 00231310231 then we need to ignore the parts that we don’t want 00231310231. Ok so lets start. Because this solution is all being done in code it will work with any AVR and indeed almost all other makes of micro controllers.

The first thing that you need is to set a timer to give you a 1ms interrupt. Because this varies between different devices I will leave this part for you to figure out.
We should now have an interrupt routine that is called every millisecond.

In my system, A is connected to PortB.1 and B is connected to PortB.0 The way pin A and B are connected is not important, but you will have to make sure you take it into account as it ‘reverses’ the direction of the information from the encoder.

In our 1ms Interupt Service Routine (ISR) we need this code:

 
    PB0 = PB0 << 1;    //this is part of our filter - every time we enter the ISR we shift the previous reading to the left by 1       
    PB1 = PB1 << 1;   //it makes room for the bit we are about to read
    PB0 = (PORTB.IN & 1) ?PB0 | 1:PB0;//B input - if the pin of PortB.0 is high then OR the variable with 1
    PB1 = (PORTB.IN & 2) ?PB1 | 1:PB1;//A input -  if the pin of PortB.1 is high then OR the variable with 1

These 4 lines of code read in the data from the encoder and form part of the filter. The filter simply sets a bit each time we enter this routine which is every 1ms. If the input is in a constant state we should have a byte which is full of 1’s or full of 0’s. If the input value changes between reads we will instead get a combination of 1’s and 0’s
So in the next line we just decide how many consecutive 1’s / 0’s  we need before we can accept that the input is stable. If the manufacturer states that the chatter / bounce is a maximum of 3ms then we need to wait until we see at least 3 1’s / 0’s  in a row. This will represent 3 ms because our sample rate is 1ms.

 
//AND our input variables with 0x07 (three 1's) and see if we get a value of 7 (all 1's) or 0 (all 0's)
if(((PB0 & 0x07) == 0x07 || (PB0 & 0x07) == 0 ) || ((PB1 & 0x07) == 0x07 || (PB1 & 0x07) == 0 ))

At this point we are happy that our signal has settled and is constant, so we will extract the real state of the inputs to a new variable

PBDat = (PB0 & 1) | (PB1 & 2); //PBDat now represents the real value of the encoder at this time

We are only interested in two things. Did it change since last time we checked? And if it changed is it a valid number?
How do we know if it is valid? Well if the previous number was say 3 then we could say it is only valid if it is 1 or 2 as they are the numbers that should follow 3 depending which way we turn the encoder.
To check if it is valid we enlist the help of a small array which represents the valid sequence of states of our inputs.
By taking the step value we are on and using it as the index to the array  we can store the legal next values  for that step

unsigned char QDat[] = {0x06,0x0c,0x03,0x09};

Those that are following closely will no doubt be wondering how these values relate to our expected values of 0,2,3,1
The reason they don’t look like those values is because we need to check for both sequences  0,2,3,1,0,2,3,1 and 1,3,2,0,1,3,2,0. Now there are many ways to do this,
one is to use a two-dimensional array or even two arrays, but on the day that I wrote the code I chose this one so here goes.
The count between 0 and 3 only requires 2 bits of the byte. So we can store the sequence for one direction in bits 0 & 1 and for the other direction in bits 2 & 3.

Lets assume that the encoder is at the 0 position. If we look at our sequence we can see that when turn it in one direction  we will get 2 being the next number or we will get 1 if we turn it the opposite way.
so if we store the 2 in the lower two bits it = 0000 0010 (0x02) and the 1 in the upper two bits 0000 0100 (0x04)  combined they become 0000 0110 (0x06)
which you will notice is our first entry in the array. If the encoder is at position 1 then the next legal value is either 3 or 0 so at index one of our array
we store 0000 0000 (0x00) for the 0 and 0000 1100 (0x0c) for the 3 which becomes 0000 1100 (0x0c)
By doing this for each possible value we can ‘look up’ the next legal  value in the sequence.

if((QDat[PBDatOld] & 0x03) == PBDat)

Notice that we are using the previous value of the encoder which is stored in PBDatOld as the index into our array. We AND the result with 0x03 so that only the lower 2 bits are looked at
because we are first checking one direction. If our new value held in PBDat is equal to a legal next value then this statement will be true and we can go ahead with the more mundane duty of
altering the count and deciding on the direction.

            PBDatOld = PBDat;
            if(StepCount == 0)
            {
                StepCount = 4;
                QDir = 0; //set direction
                if(QuadCount == 0)
                {
                    QuadCount = MAXCOUNT;
                }
                QuadCount--;
            }
            StepCount--;

We do exactly the same for the other direction but this time we use the upper 2 bits in the array and increment the count

        else if(((QDat[PBDatOld] >> 2) & 0x03) == PBDat)
        {
            PBDatOld = PBDat;
            StepCount++;
            if(StepCount > 3)
            {
                StepCount = 0;
                QDir = 1; //set direction
                QuadCount++;
                if(QuadCount >= MAXCOUNT)
                {
                    QuadCount = 0;
                }
            }
        }

Ok so lets put it all together.

This is the module that contains your 1 ms interrupt code:

#define MAXCOUNT 24 // this must be changed to the number of steps your encoder does in a revolution

volatile unsigned char PB0;
volatile unsigned char PB1;
volatile unsigned char PBDatOld;
volatile unsigned char StepCount;
volatile unsigned char QuadCount;
volatile unsigned char QDir;

ISR(your vector goes here)//occurs every 1ms
{
    unsigned char PBDat;

    PB0 = PB0 << 1;
    PB1 = PB1 << 1;
    PB0 = (PORTB.IN & 1) ?PB0 | 1:PB0;//B
    PB1 = (PORTB.IN & 2) ?PB1 | 1:PB1;//A
    if(((PB0 & 0x07) == 0x07 || (PB0 & 0x07) == 0 ) || ((PB1 & 0x07) == 0x07 || (PB1 & 0x07) == 0 ))
    {
        PBDat = (PB0 & 1) | (PB1 & 2);
        if((QDat[PBDatOld] & 0x03) == PBDat)
        {
            PBDatOld = PBDat;
            if(StepCount == 0)
            {
                StepCount = 4;
                QDir = 0;
                if(QuadCount == 0)
                {
                    QuadCount = 24;
                }
                QuadCount--;
            }
            StepCount--;
        }
        else if(((QDat[PBDatOld] >> 2) & 0x03) == PBDat)
        {
            PBDatOld = PBDat;
            StepCount++;
            if(StepCount > 3)
            {
                StepCount = 0;
                QDir = 1;
                QuadCount++;
                if(QuadCount > 23)
                {
                    QuadCount = 0;
                }
            }
        }
    }
}

Some helpers

This code must not be within your interrupt routine.

Firstly we create two functions which will return count and direction if a change occurs

//--------------------------------------------------------------------
//returns a 1 if the encoder value has changed.
//Direction will be changed via pointer given
//use GetQuadCount will return the value of the count
unsigned char CheckQuad(unsigned char * Direction)
{
    if(ReverseScroll)
    {
        *Direction = 1 - QDir;   
    }
    else
    {
        *Direction = QDir;
    }

    if(QuadCount != OldQuad)
    {
        OldQuad = QuadCount;
        return 1;
    }
    return 0;
}
//--------------------------------------------------------------------
//return encoder position (0 - 23)
unsigned char GetQuadCount(void)
{
    return QuadCount;
}

//--------------------------------------------------------------------

For some applications we don’t actually need the count from the encoder. We only need to know that it changed value and which direction it went

Use it like this

unsigned char Direction

if (CheckQuad(&Direction)) //only true if it changed
{
    ScrollMenu(Direction); //scroll our menu up or down
}

If a count is required then this will be how it is called

unsigned char Direction
unsigned char Count
if (CheckQuad(&Direction)) //only true if it changed
{
  Count = GetQuadCount();
  doStuff(Count,Direction);
}

Conclusion

Even though the Xmega built-in Quadrature decoding feature can make reading the decoders simply a configuration, it is not suitable for all decoder types.  As can be seen above, writing our own code to do this is a fairly simple task and it is also flexible in that it can be altered to suit our exact requirements.

 

 

 

 

]]>
https://www.dghacks.com/micro-controller/quadrature_encoders/feed/ 0
Arduino Space Invaders https://www.dghacks.com/arduino/arduino-space-invaders/ https://www.dghacks.com/arduino/arduino-space-invaders/#respond Mon, 25 Sep 2017 14:15:20 +0000 http://www.dghacks.com/?p=60 Most of the microcontroller based hardware that I develop uses some form of AVR, so when I needed to evaluate some Arduino boards it was not much of a problem because as you most likely know, they too use AVR microcontrollers. At the time I decided that a simple game on an Arduino might be a fun way to test things.  After completion I got the idea to publish it as a tutorial for beginners showing how to use Arduinos for games. Unfortunatly I never managed to finish the tutorial due to ‘paying’ projects taking priority.

Even though the tutorial was never finished, it along with the source code could still be of some help to anyone interested in game writing on a microcontroller.  I have therefore decide to publish the section that was done. It covers mostly the hardware description along with the graphic layout and explanation.

Here goes….

What to do?

So you are sitting looking at your shiny new or perhaps not so new Arduino and thinking … what can I do with it. You have already said “Hello World; made LED’s flash and sent messages to your PC – so what’s next? Let’s write a game. At first you might think this will be a bit difficult if you are just starting out but with a little help it might be easier than what you think.

 

The Game

Space Invaders was one of the first video games written where the ‘machine’ fought back. So I have chosen this game as a good starting point to writing games on an Arduino.

 

What do you need?

You will need an Arduino. I have written and tested this game on an Arduino Duemilanove clone board.  The display used is a small inexpensive Nokia 5110 LCD display.

Nokia5110LCD1

 

Of course if you are feeling brave you could salvage one from and old cell phone. This display expects to be connected to a 3.3v system. If your Arduino board does not have the option to run on 3.3v you will need some extra circuitry.  To keep things simple I have used a 4X4 Keypad shield with display interface.

4X4Keypad

 

This shield allows you to use 5v or 3.3v. Apart from providing a simple interface for the LCD it also provides the buttons that you will need for the game. If you do not use this shield you will need to change the button inputs to suit whatever inputs you are using.

Note

If you choose to use 5 volts then on the keypad make sure jumpers are removed –  jumpers bridge out limiting resistors on boards also set switch to 5 volt on keypad and Arduino

LCD

Ok its time to take a closer look at the display. The 5110 LCD is arranged as a matrix of 84 pixels across and 48 pixels down. Being a simple black and white display each pixel has only two states. It can be on / black or off / white. This allows us to control each pixel with just one bit.  Unfortunately as I am sure you know by now, not everything is simple and neither is the layout of the bytes that make up the pixels of the LCD. The following image shows how the screen is laid out. At the bottom the X axis is marked showing the pixels across starting at 0 and going to 83.

The 0 to 5 shown on the Y axis represents the 6 bytes each containing 8 bits that make up the 48 pixels from top to bottom. Not shown in this diagram is the fact that the lowest valued bit column is toward the top of the LCD in each byte. So if we wanted to turn the the pixel on at the top left of the screen we would put a 1 which is binary 00000001 in the first byte and if we put 0x80  which in binary is 1000000 it would turn on the pixel in the 8th row from the top.

ScreenLayout

Don’t get too concerned about this, the library provided below will do all the heavy lifting for you.

 

 

Lets Start Coding

Before starting let me make some things clear. The object of this article is to demonstrate that writing a game for Arduino does not have to be too complicated. It is aimed at beginner level and up. I have therefore chosen to keep the code as basic and simple as possible and have avoided more advanced methods wherever possible. It is therefore not aimed to teach the best coding methods but rather aimed at keeping things simple enough to follow and understand.

 

The Enemy

Now that we have a good idea of how the screen is laid out we can look at some of the items that will be displayed. Being an invaders game we need some invaders.  Just as in the original game we have three different invaders. In order to give them some basic animation each invader has two different bitmaps. Let’s look at one of them and see how we get the image into our code.

 

Inv0

We can see that it is 8 pixels high and 5 pixels wide.  To make it easy to use in our program we will convert it to hexadecimal. The bitmap has been laid out the same as the display. Each column is a single byte with the least significant bit toward the top. To convert it we do the following. Assign a value to each row starting at the top as follows.

Inv0a

Start in the left most column. Start at the top and add the values in the first 4 rows in this column, where the pixels are on (black). The total is 12. We express that as a hexadecimal value ‘C’ . Now add the fields in the remaining 4 rows in this column, which are on. This gives 5. Remembering that the bits toward the bottom represent the most significant values. We combine them together to get the hexadecimal value of 5C. In the C programming language this is written as 0x5C.

 

We do the same for each column and will get the following values:  0x5C,0xB6,0x3F,0xB6,0x5C.  We can now put these into an array. To help our image handling functions we will also put the number of columns making up our image (the width) into the array. This invader is 5 pixels wide.

Our array definition looks like this: unsigned char Invader[6] = {0x05,0x5C,0xB6,0x3F,0xB6,0x5C};

 

That was easy…. maybe too easy? Don’t forget that I said there were two images for each invader to give some animation. Say hello to his deformed twin:

Inv1

Together we get:

Inv0

The array for this one is:  Invader[6] = {0x05, 0xDC,0x36,0x3F,0x36,0xDC };

 

To keep everything together and to make our program a little easier we will put both of them in one two dimension array.

 

unsigned char InvTop[2][6] PROGMEM =

{

{0x05,0x5C,0xB6,0x3F,0xB6,0x5C},//inv0

{0x05,0xDC,0x36,0x3F,0x36,0xDC} //inv1

};

 

Let examine this declaration. We have InvTop[2][6]. This simply says that this array contains two arrays each holding six bytes of data. PROGMEM ??? This is to tell the compiler to put this data into the Flash memory area of the processor instead of on the Ram area. We do this because the Ram area on this chip is only 1024 bytes whereas the Flash area is 8192 bytes.  This does add another requirement when we want to use the data. We have to tell the compiler that it must look for the data in Flash and also provide it a method to read the data. We use the “pgm_read_byte” instructions.

 

Apart from the invaders we need a cannon, missiles, explosions, UFO and some shields. I have provided the shields but their use has not been coded.  Here are the main actors

Gun1 Inv1 Inv0 Inv3 Inv2 Inv4 Inv5 Ufo

 

Each of them has been put into the code in the same way as detailed above

 

Start at the Top

We need to include a couple hardware libraries for the display and keypad

#include “IBridge_n5110_lcd.h”//libraries to control the LCD. You can get it here

#include “IBridge_Keypad.h”//keypad library. It is here

Once you have downloaded these files unzip them into the ‘libraries’ folder which you will find within the Arduino software path.

One last thing… download the main program file HERE 🙂

 

 

 

 

 

 

 

]]>
https://www.dghacks.com/arduino/arduino-space-invaders/feed/ 0