conways game of life and mstimer2 , 328 on 0018ide

Hi, i have a 328 and using the 0018 ide.
im trying to get conways game of life working using mstimer2 as i get the impression that frequencytimer2 doesnt work. i cant get it to work anyway as i know zilch about this stuff. i just need this to work for a degree project. Heres the code for game of life, mstimer2.cpp, and mstimer2.h
#include <MsTimer2.h>

/*

  • Conway’s “Life”
  • Adapted from the Life example
  • on the Processing.org site
    */

#include <MsTimer2.h>

byte analogPin = 5;
byte col = 0;
byte leds[8][8];

// pin[xx] on led matrix connected to nn on Arduino (-1 is dummy to make array start at pos 1)
int pins[17]= {-1, 5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};

// col[xx] of leds = pin yy on led matrix
int cols[8] = {pins[13], pins[3], pins[4], pins[10], pins[06], pins[11], pins[15], pins[16]};

// row[xx] of leds = pin yy on led matrix
int rows[8] = {pins[9], pins[14], pins[8], pins[12], pins[1], pins[7], pins[2], pins[5]};

#define DELAY 0
#define SIZE 8
extern byte leds;
byte world[2];
long density = 50;

void setup() {
setupLeds();
randomSeed(analogRead(5));
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (random(100) < density) {
world*[j][0] = 1;*

  • }*
  • else {*
    _ world*[j][0] = 0;_
    _
    }_
    _ world[j][1] = 0;
    }
    }
    }
    void loop() {
    // Display current generation*
    * for (int i = 0; i < SIZE; i++) {
    for (int j = 0; j < SIZE; j++) {
    leds[j] = world[j][0];
    }
    }
    delay(DELAY);
    // Birth and death cycle*

    * for (int x = 0; x < SIZE; x++) {
    for (int y = 0; y < SIZE; y++) {
    // Default is for cell to stay the same*

    * world[y][1] = world[y][0];
    int count = neighbours(x, y);
    if (count == 3 && world[y][0] == 0) {
    // A new cell is born*

    * world[y][1] = 1;
    }
    if ((count < 2 || count > 3) && world[y][0] == 1) {
    // Cell dies*

    * world[y][1] = 0;
    }
    }
    }*_

* // Copy next generation into place*
* for (int x = 0; x < SIZE; x++) {*
* for (int y = 0; y < SIZE; y++) {*
* world[x][y][0] = world[x][y][1];*
* }*
* }*
}
int neighbours(int x, int y) {
return world[(x + 1) % SIZE][y][0] +
* world[x][(y + 1) % SIZE][0] +*
* world[(x + SIZE - 1) % SIZE][y][0] +*
* world[x][(y + SIZE - 1) % SIZE][0] +*
* world[(x + 1) % SIZE][(y + 1) % SIZE][0] +*
* world[(x + SIZE - 1) % SIZE][(y + 1) % SIZE][0] +*
* world[(x + SIZE - 1) % SIZE][(y + SIZE - 1) % SIZE][0] +*
* world[(x + 1) % SIZE][(y + SIZE - 1) % SIZE][0];*
}
void setupLeds() {
* // sets the pins as output*
* for (int i = 1; i <= 16; i++) {*
_ pinMode(pins*, OUTPUT);
}
// set up cols and rows*

* for (int i = 1; i <= 8; i++) {
digitalWrite(cols[i - 1], LOW);
}
for (int i = 1; i <= 8; i++) {
digitalWrite(rows[i - 1], LOW);
}*_

* clearLeds();*

* // Turn off toggling of pin 11*
* // Set refresh rate (interrupt timeout period)*
* // Set interrupt routine to be called*
}
void clearLeds() {
* // Clear display array*
* for (int i = 0; i < 8; i++) {*
* for (int j = 0; j < 8; j++) {*
_ leds*[j] = 0;
}
}
}
// Interrupt routine*

void display() {
* digitalWrite(cols[col], LOW); // Turn whole previous column off*
* col++;
if (col == 8) {
col = 0;
}
for (int row = 0; row < 8; row++) {
if (leds[col][7 - row] == 1) {
digitalWrite(rows[row], LOW); // Turn on this led*

* }
else {
digitalWrite(rows[row], HIGH); // Turn off this led*

* }
}
digitalWrite(cols[col], HIGH); // Turn whole column on at once (for equal lighting times)
delayMicroseconds(900); // Delay so that on times are longer than off time = brighter leds*

}
now mstimer2.cpp
/
MsTimer2.h - Using timer2 with 1ms resolution*

* Javier Valencia javiervalencia80@gmail.com*_

* History:*
* 29/May/09 - V0.5 added support for Atmega1280 (thanks to Manuel Negri)*
* 19/Mar/09 - V0.4 added support for ATmega328P (thanks to Jerome Despatis)*
* 11/Jun/08 - V0.3*
* changes to allow working with different CPU frequencies*
* added support for ATMega128 (using timer2)*
* compatible with ATMega48/88/168/8*
* 10/May/08 - V0.2 added some security tests and volatile keywords*
* 9/May/08 - V0.1 released working on ATMEGA168 only*

* This library is free software; you can redistribute it and/or*
* modify it under the terms of the GNU Lesser General Public*
* License as published by the Free Software Foundation; either*
* version 2.1 of the License, or (at your option) any later version.*
* This library is distributed in the hope that it will be useful,*
* but WITHOUT ANY WARRANTY; without even the implied warranty of*
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU*
* Lesser General Public License for more details.*
* You should have received a copy of the GNU Lesser General Public*
* License along with this library; if not, write to the Free Software*
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*
*/
#include <MsTimer2.h>
unsigned long MsTimer2::msecs;
void (*MsTimer2::func)();
volatile unsigned long MsTimer2::count;
volatile char MsTimer2::overflowing;
volatile unsigned int MsTimer2::tcnt2;
void MsTimer2::set(unsigned long ms, void (*f)()) {
* float prescaler = 0.0;*

#if defined (AVR_ATmega168) || defined (AVR_ATmega48) || defined (AVR_ATmega88) || defined (AVR_ATmega328P) || (AVR_ATmega1280)
* TIMSK2 &= ~(1<<TOIE2);*
* TCCR2A &= ~((1<<WGM21) | (1<<WGM20));*
* TCCR2B &= ~(1<<WGM22);*
* ASSR &= ~(1<<AS2);*
* TIMSK2 &= ~(1<<OCIE2A);*

* if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64*
* TCCR2B |= (1<<CS22);*
* TCCR2B &= ~((1<<CS21) | (1<<CS20));*
* prescaler = 64.0;*
* } else if (F_CPU < 1000000UL) { // prescaler set to 8*
* TCCR2B |= (1<<CS21);*
* TCCR2B &= ~((1<<CS22) | (1<<CS20));*
* prescaler = 8.0;*
* } else { // F_CPU > 16Mhz, prescaler set to 128*
* TCCR2B |= ((1<<CS22) | (1<<CS20));*
* TCCR2B &= ~(1<<CS21);*
* prescaler = 128.0;*
* }*
#elif defined (AVR_ATmega8)
* TIMSK &= ~(1<<TOIE2);*
* TCCR2 &= ~((1<<WGM21) | (1<<WGM20));*
* TIMSK &= ~(1<<OCIE2);*
* ASSR &= ~(1<<AS2);*

* if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64*
* TCCR2 |= (1<<CS22);*
* TCCR2 &= ~((1<<CS21) | (1<<CS20));*
* prescaler = 64.0;*
* } else if (F_CPU < 1000000UL) { // prescaler set to 8*
* TCCR2 |= (1<<CS21);*
* TCCR2 &= ~((1<<CS22) | (1<<CS20));*
* prescaler = 8.0;*
* } else { // F_CPU > 16Mhz, prescaler set to 128*
* TCCR2 |= ((1<<CS22) && (1<<CS20));*
* TCCR2 &= ~(1<<CS21);*
* prescaler = 128.0;*
* }*
#elif defined (AVR_ATmega128)
* TIMSK &= ~(1<<TOIE2);*
* TCCR2 &= ~((1<<WGM21) | (1<<WGM20));*
* TIMSK &= ~(1<<OCIE2);*

* if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64*
* TCCR2 |= ((1<<CS21) | (1<<CS20));*
* TCCR2 &= ~(1<<CS22);*
* prescaler = 64.0;*
* } else if (F_CPU < 1000000UL) { // prescaler set to 8*
* TCCR2 |= (1<<CS21);*
* TCCR2 &= ~((1<<CS22) | (1<<CS20));*
* prescaler = 8.0;*
* } else { // F_CPU > 16Mhz, prescaler set to 256*
* TCCR2 |= (1<<CS22);*
* TCCR2 &= ~((1<<CS21) | (1<<CS20));*
* prescaler = 256.0;*
* }*
#endif

tcnt2 = 256 - (int)((float)F_CPU * 0.001 / prescaler);

* if (ms == 0)*
* msecs = 1;*
* else*
* msecs = ms;*

* func = f;*
}
void MsTimer2::start() {
* count = 0;*
* overflowing = 0;*
#if defined (AVR_ATmega168) || defined (AVR_ATmega48) || defined (AVR_ATmega88) || defined (AVR_ATmega328P) || (AVR_ATmega1280)
* TCNT2 = tcnt2;*
* TIMSK2 |= (1<<TOIE2);*
#elif defined (AVR_ATmega128)
* TCNT2 = tcnt2;*
* TIMSK |= (1<<TOIE2);*
#elif defined (AVR_ATmega8)
* TCNT2 = tcnt2;*
* TIMSK |= (1<<TOIE2);*
#endif
}
void MsTimer2::stop() {
#if defined (AVR_ATmega168) || defined (AVR_ATmega48) || defined (AVR_ATmega88) || defined (AVR_ATmega328P) || (AVR_ATmega1280)
* TIMSK2 &= ~(1<<TOIE2);*
#elif defined (AVR_ATmega128)
* TIMSK &= ~(1<<TOIE2);*
#elif defined (AVR_ATmega8)
* TIMSK &= ~(1<<TOIE2);*
#endif
}
void MsTimer2::_overflow() {
* count += 1;*

* if (count >= msecs && !overflowing) {*
* overflowing = 1;*
* count = 0;*
_ (func)();
overflowing = 0;
}
}_

ISR(TIMER2_OVF_vect) {
#if defined (AVR_ATmega168) || defined (AVR_ATmega48) || defined (AVR_ATmega88) || defined (AVR_ATmega328P) || (AVR_ATmega1280)
_ TCNT2 = MsTimer2::tcnt2;_
#elif defined (AVR_ATmega128)
_ TCNT2 = MsTimer2::tcnt2;_
#elif defined (AVR_ATmega8)
_ TCNT2 = MsTimer2::tcnt2;
#endif*

* MsTimer2::overflow();*
}

now mstimer2.h
#ifndef MsTimer2_h
#define MsTimer2_h
#include <avr/interrupt.h>
namespace MsTimer2 {
* extern unsigned long msecs;*
_ extern void (func)();
extern volatile unsigned long count;
extern volatile char overflowing;
extern volatile unsigned int tcnt2;*_

_ void set(unsigned long ms, void (f)());
void start();
void stop();_

void overflow();*
}
#endif
i hope someone can help me with this, im going insane with forum merry go round. please bare in mind that i know nothing of how to program. im only an artist trying to add a little pizzaz to a light. thanks. jay_

I have had success using the Timer1 library with that code.

You can find the Timer1 library at http://www.arduino.cc/playground/Code/Timer1. The “install instructions” on that page are no longer valid for IDE 0018, so create a TimerOne (note the spelling) directory in the libraries folder. Download the zip file and put the TimerOne.h and TimerOne.cpp files from it into that new directory.

Change your

[b]    #include <MsTimer2.h>[/b]

to

[b]    #include <TimerOne.h>[/b]

and add the following code somewhere in setup().

  // Establish an interrupt
  Timer1.initialize(100); // interrupt every 100 microseconds
  Timer1.attachInterrupt(display); // control will go to the display() function when the interrupt happens

Your code compiles with those changes, but I don’t have a spare LED matrix to test with. Let us know how it goes, for the benefit of the next person to find this thread through a search of some kind.

Hi, ive just done what you have suggested and bingo! it compiles. got to wait 12 agonising hours now to see if it works on my matrix at uni. so its fingers, toes and balls crossed. Thankyou for such a quick reply. ill let you know tomorrow what happens.

HI, The new problem is that it tries to use com1 serial port to output, my board is on com 10. any ideas. thanks jay

[edit]The new problem is that it tries to use com1 serial port to output[/edit]
I don’t understand. “It” probably doesn’t mean the sketch, since there are no serial commands there, and the sketch does not use digital pin 0 or 1. Does “it” refer to the Arduino IDE? If so, pull down Tools > Serial Port and select your com10 port before uploading. Com10 will only be available in the list when your Arduino is connected to your computer via the USB cable.

Can you post your operating system and version if that is not the solution?

hi, ive managed to compile and upload to the board. However, there are a few leds lit but no movement whatsoever. The matrix is directly connected to the output pins as shown in the example with the mod board(or whatever its called). Any ideas? Heres the code with 2 additional interupt lines as highlighted.
#include <TimerOne.h>

/*

  • Conway’s “Life”
  • Adapted from the Life example
  • on the Processing.org site
    */

byte analogPin = 5;
byte col = 0;
byte leds[8][8];

// pin[xx] on led matrix connected to nn on Arduino (-1 is dummy to make array start at pos 1)
int pins[17]= {-1, 5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};

// col[xx] of leds = pin yy on led matrix
int cols[8] = {pins[13], pins[3], pins[4], pins[10], pins[06], pins[11], pins[15], pins[16]};

// row[xx] of leds = pin yy on led matrix
int rows[8] = {pins[9], pins[14], pins[8], pins[12], pins[1], pins[7], pins[2], pins[5]};

#define DELAY 0
#define SIZE 8
extern byte leds;
byte world[2];
long density = 50;

void setup() {
setupLeds();
randomSeed(analogRead(5));
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (random(100) < density) {
world*[j][0] = 1;*

  • }*
  • else {*
    _ world*[j][0] = 0;_
    _
    }_
    _ world[j][1] = 0;
    }
    }
    }
    void loop() {
    // Display current generation*
    * for (int i = 0; i < SIZE; i++) {
    for (int j = 0; j < SIZE; j++) {
    leds[j] = world[j][0];
    }
    }
    delay(DELAY);
    // Establish an interrupt
    Timer1.initialize(100); // interrupt every 100 microseconds
    Timer1.attachInterrupt(display); // control will go to the display() function when the interrupt happens
    // Birth and death cycle*

    * for (int x = 0; x < SIZE; x++) {
    for (int y = 0; y < SIZE; y++) {
    // Default is for cell to stay the same*

    * world[y][1] = world[y][0];
    int count = neighbours(x, y);
    if (count == 3 && world[y][0] == 0) {
    // A new cell is born*

    * world[y][1] = 1;
    }
    if ((count < 2 || count > 3) && world[y][0] == 1) {
    // Cell dies*

    * world[y][1] = 0;
    }
    }
    }*_

* // Copy next generation into place*
* for (int x = 0; x < SIZE; x++) {*
* for (int y = 0; y < SIZE; y++) {*
* world[x][y][0] = world[x][y][1];*
* }*
* }*
}
int neighbours(int x, int y) {
return world[(x + 1) % SIZE][y][0] +
* world[x][(y + 1) % SIZE][0] +*
* world[(x + SIZE - 1) % SIZE][y][0] +*
* world[x][(y + SIZE - 1) % SIZE][0] +*
* world[(x + 1) % SIZE][(y + 1) % SIZE][0] +*
* world[(x + SIZE - 1) % SIZE][(y + 1) % SIZE][0] +*
* world[(x + SIZE - 1) % SIZE][(y + SIZE - 1) % SIZE][0] +*
* world[(x + 1) % SIZE][(y + SIZE - 1) % SIZE][0];*
}
void setupLeds() {
* // sets the pins as output*
* for (int i = 1; i <= 16; i++) {*
_ pinMode(pins*, OUTPUT);
}
// set up cols and rows*

* for (int i = 1; i <= 8; i++) {
digitalWrite(cols[i - 1], LOW);
}
for (int i = 1; i <= 8; i++) {
digitalWrite(rows[i - 1], LOW);
}*_

* clearLeds();*

}
void clearLeds() {
* // Clear display array*
* for (int i = 0; i < 8; i++) {*
* for (int j = 0; j < 8; j++) {*
_ leds*[j] = 0;
}
}
}
// Interrupt routine*

void display() {
* digitalWrite(cols[col], LOW); // Turn whole previous column off*
* col++;
if (col == 8) {
col = 0;
}
for (int row = 0; row < 8; row++) {
if (leds[col][7 - row] == 1) {
digitalWrite(rows[row], LOW); // Turn on this led*

* }
else {
digitalWrite(rows[row], HIGH); // Turn off this led*

* }
}
digitalWrite(cols[col], HIGH); // Turn whole column on at once (for equal lighting times)
delayMicroseconds(900); // Delay so that on times are longer than off time = brighter leds*

}_

Why do attach the interrupt handler in loop? Isn't that something that needs to be done only once, in setup? Or, are you detaching it somewhere that I didn't see?

One more question. Can you learn to post code properly, using the # button on the top row?

PaulS is right, the code that establishes the interrupt routine should go somewhere in setup(), as noted in reply #1. However, once the interrupt is established, re-establishing the same interrupt the same way over and over again inside loop() should not affect the rest of the logic or the display. [edit]Hmmmm. Unless re-setting up an interrupt before it has a chance to fire keeps it from firing even the first time. So make the software change first -- move the highlighted lines of your code to the beginning of setup() -- and if things work after that you're all set, otherwise, continue with the rest of this reply.[/edit]

The matrix is directly connected to the output pins as shown in the example with the mod board(or whatever its called).

Your matrix may be wired incorrectly. Can you please provide - a link to the example you mentioned (I have no clue which example you're looking at)- a link to the data sheet for the LED matrix you have (it may be a different brand or model than the one in the example you are looking at)- a list of which of your Arduino pins is connected to which LED matrix pin, in the following form: Arduino digital pin 0 - no connection Arduino digital pin 1 - no connection Arduino digital pin 2 - LED matrix pin #__ Arduino digital pin 3 - LED matrix pin #__ Arduino digital pin 4 - LED matrix pin #__ Arduino digital pin 5 - LED matrix pin #__ etc. (I will verify row/column attachments with the data sheet and the code)

hi, the matrix is ok i m sure because ive run your test software that turns on one led at a time etc, its fine and so is the scrolling message one. ill try your suggestion of moving the interupt code but im clueless as to where exactly i should put it. do you mean pit it directly underneat the void setup () { line or above it? thanks. jay ;D ;D

Move it directly underneath void setup () {

hi, its working but there is a problem with the display now.It displays three columns more than the rest and when it finishes doing its thing like its supposed to it then displays them permenantly. Ive also tried the Hello one using timer one to see if that works. it does the same thing. like i said it works fine with your test software etc. my board is the duemeliova or something. The code was written for the deicimila. Any ideas? also i moved the code underneath void loop instead cos it didnt work under void setup. thanks

It displays three columns more than the rest and when it finishes doing its thing like its supposed to it then displays them permenantly.

Well, you managed to completely lose me with that one.

like i said it works fine with your test software etc.

That’s good. Except that I never posted any test software.

also i moved the code underneath void loop instead cos it didnt work under void setup.

So now it is working with the interrupt initialization in loop() when you reported in Reply #5 that it was not working with it there. At least it is working for you now.

hi, ive done it at last. it was the pin definitions at the beginning. i made my own matrix so it was a simple matter of naming the row pins from 9-16, and the column pins from 1-8. any ideas on how to make this loopable when it stops. at the ,moment i have to do a hard reset?

hi, i never meant you specifically. i meant the arduino people. sorry about the confusing post. i was confused too. i have never done anything like this before so its all very new to me. i appreciate your help non the less. thanks to you its working and i can now sleep. still the problem of making it loop though when the game of life cycle has ran its course. I have to hard reset at that point to run again. is there any way to do this in the software when the game of life comes to a point where it either repeats constantly, freezes with a few leds lit or clears the display totally. this would be a great help to me. thanks

... or you could go by mechanical logic...

http://www.youtube.com/watch?v=13GOFa1C4e4

-Fletcher