11.03
Santa came early this year and brought me a S65-Shield revision 1.2 from watterott
It consists of :
- a Siemens S65 16-bit color screen with 172×136 pixels
- a rotary switch (left-right-press)
- a micro-SD slot (bottom)
You can visit the project page to check progress made to the libraries and hardware.The most recent library is v0.08 . It’s actually more like 3 libraries: ‘S65Display’, ‘RotaryEncoder’ and ‘SDCard’.
You can check the documentation that comes with the libraries to view this baby shields’ possibilities. So far this shield seems to be a bargain (compaired to other display-shields out there) selling at only €35 that’s equal to $51.36600 or 4640.5276 Japanese Yen or 149.793533 Polish Zloty or your virginity if you’re misfortuned enough to live in one of those countries, anyhow.
It has some pretty long headers which make it easy to mount on top of the tallest board you own.
I don’t have a microSD card at hand so I can’t test the SDCard library for now. Which sucks since you can load images stored on the microSD and display them on the screen. You can also use the images for buttons, icons, etc in your sketches… how cool is that?
Here’s an example of the awsome S65-Shield in action on an Arduino Duemilanove with 328 Atmel running a Game of Life sketch. I am not the author of this code, he gave me the code for testing and learning purposes. I just added the rotary delay. Maybe he’ll give his consent later so I can post the code online. Foo Joku gave his consent, the code is posted after the video.
The display and colors look much better in real life, this video was shot with an old digital camera in bad light conditions.
GOL code:
#include <S65Display.h>
#include <RotaryEncoder.h>
#define GRID_X 28
#define GRID_Y 20
#define GRID_X_OFFSET 4
#define GRID_Y_OFFSET 6
#define COLOUR_SWITCH_INTERVAL 30
#define MAX_GENERATIONS 250
S65Display lcd;
RotaryEncoder encoder;
uint8_t grid[2][GRID_X][GRID_Y];
uint8_t current_grid = 0;
uint8_t generations = 0;
uint8_t r = 255,g = 0, b = 0;
// Encoder must be serviced regularly.
ISR(TIMER2_OVF_vect)
{
TCNT2 -= 250; //1000 Hz
encoder.service();
}
void setup()
{
lcd.init(4);
encoder.init();
// More encoder stuff
//init Timer2
TCCR2B = (1<<CS22); //clk=F_CPU/64
TCNT2 = 0x00;
TIMSK2 |= (1<<TOIE2); //enable overflow interupt
sei();
initGrid();
lcd.clear(0);
drawGrid();
}
void loop()
{
//delay(50);
checkEncoder();
runGrid();
drawGrid();
generations++;
if (generations > MAX_GENERATIONS || cmpGrid()) {
generations = 0;
initGrid();
}
cycleColour();
cycleColour();
cycleColour();
}
int cmpGrid()
{
int i, j;
for (i=0; i < GRID_Y; i++) {
for (j=0; j < GRID_X; j++) {
if (grid[0][i][j] != grid[1][i][j]) { return 0; }
}
}
return 1;
}
void initGrid()
{
int i, j;
int t;
lcd.clear(0);
current_grid = 0;
for (i = 0; i < GRID_X; i++) {
for (j = 0; j < GRID_Y; j++) {
if ((uint8_t)random(255) % 3 == 0) {
grid[0][i][j] = 1;
} else {
grid[0][i][j] = 0;
}
}
}
}
void runGrid()
{
uint8_t x, y;
int count;
char string[2] = {0,0};
uint8_t value = 0;
uint8_t new_grid;
new_grid = 1 - current_grid;
for (y = 0; y < GRID_Y; y++) {
for (x = 0; x < GRID_X; x++) {
count = count_neighbours(x, y);
string[0] = count+48;
if (count < 2 || count > 3) { value = 0; }
else if (count == 3) { value = 3; }
else { value = grid[current_grid][x][y]; }
grid[new_grid][x][y] = value;
}
}
current_grid = new_grid;
}
int count_neighbours(int x, int y)
{
int i, j;
int sx;
int result = 0;
x--;
y--;
for (i = 0; i < 3; i++) {
if (y < 0 || y > (GRID_Y - 1)) { continue; }
for (j = 0; j < 3; j++) {
if (x < 0 || x > (GRID_X - 1)) { continue; }
if (i==1 && j == 1) { x++; continue; } // skip centre
if (grid[current_grid][x][y]) { result++; }
x++;
}
y++;
x -= 3;
}
return result;
}
void drawGrid()
{
uint8_t x, y;
uint8_t cx, cy;
uint8_t grid_next_colour = 0;
cx = GRID_X_OFFSET;
cy = GRID_Y_OFFSET;
for (y = 0; y < GRID_Y; y++) {
cx = GRID_X_OFFSET;
for (x = 0; x < GRID_X; x++) {
if (grid[1-current_grid][x][y] != grid[current_grid][x][y]) {
if(grid[current_grid][x][y]) {
lcd.drawRect(cx+1, cy+1, cx+5, cy+5, RGB(r,g,b));
} else {
lcd.drawRect(cx, cy, cx+6, cy+6, 0);
}
}
cx += 6;
}
cy += 6;
}
}
inline void cycleColour()
{
if (!b && r) { r-=5; g+=5; }
else if (g) { g-=5; b+=5; }
else if (b) { b-=5; r+=5; }
}
void checkEncoder(void)
{
int8_t press;
press = encoder.sw();
if ( !press ) { return; }
if (SW_PRESSED == press || SW_PRESSEDLONG == press) {
initGrid();
lcd.clear(0);
}
}

Heya,
That looks suspiciously like my (foojoku) version of the GoL :). If it is, you’re welcome to post the code or, really, do whatever else you want with it.
Hi Foo Joku,
It is indeed your code but I didn’t get to asking your approval to distribute so I didn’t post it. But now I will since several people have asked me for the code in the past few months. Now that I have some more time I’ll soon write my own versions of GoL.
Greets,
Tom