# Batsocks TellyMate Shield

Thought you might like to see some pics of the Batsocks TellyMate Shield hooked up to my 47" LCD TV:-

The quality is really impressive. I am wondering if somebody already started implementing some old fashioned apps, like tennis, or even come up with a ZX Spectrum "replacement".

I'm going to give 'Pong' a go for starters :)

Hi Mike, I starting working on that as well, how far along is yours?

Not even started yet ::)

Here is a version of pong for the TellyMate. The gameplay is based on some code Tom Igoe posted here: http://www.tigoe.net/pcomp/code/category/Processing/454#more-454

``````/*
TellyPong
pong for the TellyMate shield
based on gameplay created by Tom Igoe http://www.tigoe.net/pcomp/code/category/Processing/454#more-454
modified by mem 20 May 2009

This example uses the TellyMate shield http://www.batsocks.co.uk/products/Other/TellyMate%20Shield.htm
*/

#define RIGHT_PIN 0  // pins connected to pots (2 and 0 are sliders 1 and 3 on dangershield)
#define LEFT_PIN  2

// define the edges of the screen:
#define HEIGHT 25
#define WIDTH  38
#define LEFT    0
#define RIGHT  (WIDTH -1)
#define TOP     0
#define BOTTOM (HEIGHT-1)

#define PADDLESIZE  1      // this how many pixels the paddle extends top and bottom
#define SPEED    4000      // how many milliseconds it takes the ball to move across the screen

#define BALL      'o'      // character code for ball

#define CHAR_ESC "\x1B"    // escape character used in TellyMate commands

int ballX = WIDTH/2;          // X position of the ball
int ballY = HEIGHT/2;         // Y position of the ball
int ballDirectionY = 1;       // X direction of the ball
int ballDirectionX = 1;       // Y direction of the ball

int rightPaddleY = 0;         // X position of the center of the right paddle
int leftPaddleY = 0;          // Y position of the center of the right paddle

int prevRight = -1;           // holds previous paddle position
int prevLeft  = -1;           // set to -1 to force display on startup

long timeStamp = 0;           // time stamp to control the pauses between ball moves
long interval = SPEED/WIDTH ; // interval in milliseconds between ball moves
boolean gamePaused = false;   // state of the game

void setup() {
Serial.begin(57600); //57k6 baud
screen_clear();
Serial.println("TellyPong!");
cursor_show(false); // turn cursor off
delay(1000);
screen_clear();
}

void loop() {
// move the ball:
if (gamePaused) {
if (millis() - timeStamp > interval*10) {
// if enough time has passed, start the game again:
gamePaused = false;
}
}
// if the game isn't paused, and enough time between ball moves
// has passed, move the ball and update the timestamp:
else {
if (millis() - timeStamp > interval) {
moveBall();
timeStamp = millis();
}
}
}

// read the sensors for X and Y values:
}
}
}

void moveBall() {
// check to see if the ball is in the horizontal range

// right:
if (ballX >= RIGHT - 1) {
// if the ball's next Y position is between
// the top and bottom of the paddle, reverse its  X direction:
// reverse the ball horizontal direction:
ballDirectionX = -ballDirectionX;
}
}

// left:
if (ballX <= LEFT + 1) {
// if the ball's next Y position is between
// the top and bottom of the paddle, reverse its  X direction:
// reverse the ball horizontal direction:
ballDirectionX = -ballDirectionX;
}
}

// if the ball goes off the screen bottom,
// reverse its Y direction:
if (ballY == BOTTOM) {
ballDirectionY = -ballDirectionY;
}
// if the ball goes off the screen top,
// reverse its X direction:
if (ballY == TOP) {
ballDirectionY = -ballDirectionY;
}

// clear the ball's previous position:
screenShowXY(' ', ballX, ballY);

// if the ball goes off the screen left or right:
if ((ballX == LEFT) || (ballX == RIGHT)) {
// reset the ball:
ballX = WIDTH/2;
;
ballY = HEIGHT/2;
// pause  and note the time you paused:
gamePaused = true;
timeStamp = millis();
}
// increment the ball's position in both directions:
ballX = ballX + ballDirectionX;
ballY = ballY + ballDirectionY;

// if the game isn't paused, set the ball
// in its new position:
if (!gamePaused) {
// set the new position:
screenShowXY(BALL, ballX, ballY);
}
}

{
{
}
}

// TellyMate helper functions

void screenShowXY( char ch, int x, int y){
// display the given character at the screen x and y location
cursor_move(y,x);
Serial.print(ch);
}
void screen_clear( void )
{ // <ESC>E
Serial.print( CHAR_ESC "E" );
}

void cursor_move( uint8_t row , uint8_t col )
{ // <ESC>Yrc
Serial.print( CHAR_ESC "Y" ) ;
Serial.print((unsigned char)(32 + row)) ;
Serial.print((unsigned char)(32 + col)) ;
}

void cursor_show( bool show )
{ // <ESC>e or <ESC>f
Serial.print( CHAR_ESC ) ;
Serial.print( show?'e':'f' ) ;
}
``````

Nice one. I haven't got that shield but will modify it for my kit. Thanks!

I haven’t got that shield but will modify it for my kit

what modificaitons ? it looks like we use the same shield.

The 'dangershield' mentioned in your code.

You only need to set the analog pin assignments for your pots. I am not using any of the other features of the DangerShield - but it would be cool to use the piezo to add sound for ball contacts, and perhaps use the swtiches to start and pause the game. hmmm

here a version that uses a speaker or piezo on pin 3 for sound.

``````/*
TellyPong
pong for the TellyMate shield
based on gameplay created by Tom Igoe http://www.tigoe.net/pcomp/code/category/Processing/454#more-454
modified by mem 20 May 2009

This example uses the TellyMate shield http://www.batsocks.co.uk/products/Other/TellyMate%20Shield.htm
*/

#define RIGHT_PIN 0  // pins connected to pots (2 and 0 are sliders 1 and 3 on dangershield)
#define LEFT_PIN  2

#define BUZZER_PIN 3 // digital pin connected to a piezo buzzer or speaker
#define EDGE_SOUND   500

// define the edges of the screen:
#define HEIGHT 25
#define WIDTH  38
#define LEFT    0
#define RIGHT  (WIDTH -1)
#define TOP     0
#define BOTTOM (HEIGHT-1)

#define PADDLESIZE  1      // this how many pixels the paddle extends top and bottom
#define SPEED    4000      // how many milliseconds it takes the ball to move across the screen

#define BALL      'o'      // character code for ball

#define CHAR_ESC "\x1B"    // escape character used in TellyMate commands

int ballX = WIDTH/2;          // X position of the ball
int ballY = HEIGHT/2;         // Y position of the ball
int ballDirectionY = 1;       // X direction of the ball
int ballDirectionX = 1;       // Y direction of the ball

int rightPaddleY = 0;         // X position of the center of the right paddle
int leftPaddleY = 0;          // Y position of the center of the right paddle

int prevRight = -1;           // holds previous paddle position
int prevLeft  = -1;           // set to -1 to force display on startup

long timeStamp = 0;           // time stamp to control the pauses between ball moves
long interval = SPEED/WIDTH ; // interval in milliseconds between ball moves
boolean gamePaused = false;   // state of the game

void setup() {
pinMode(BUZZER_PIN, OUTPUT); // if using speaker
Serial.begin(57600); //57k6 baud
screen_clear();
Serial.println("TellyPong!");
cursor_show(false); // turn cursor off
delay(1000);
screen_clear();
}

void loop() {
// move the ball:
if (gamePaused) {
if (millis() - timeStamp > interval*10) {
// if enough time has passed, start the game again:
gamePaused = false;
}
}
// if the game isn't paused, and enough time between ball moves
// has passed, move the ball and update the timestamp:
else {
if (millis() - timeStamp > interval) {
moveBall();
timeStamp = millis();
}
}
}

// read the sensors for X and Y values:
}
}
}

void moveBall() {
// check to see if the ball is in the horizontal range

// right:
if (ballX >= RIGHT - 1) {
// if the ball's next Y position is between
// the top and bottom of the paddle, reverse its  X direction:
// reverse the ball horizontal direction:
ballDirectionX = -ballDirectionX;
}
}

// left:
if (ballX <= LEFT + 1) {
// if the ball's next Y position is between
// the top and bottom of the paddle, reverse its  X direction:
// reverse the ball horizontal direction:
ballDirectionX = -ballDirectionX;
}
}

// if the ball goes off the screen bottom,
// reverse its Y direction:
if (ballY == BOTTOM) {
ballDirectionY = -ballDirectionY;
}
// if the ball goes off the screen top,
// reverse its X direction:
if (ballY == TOP) {
ballDirectionY = -ballDirectionY;
}

// clear the ball's previous position:
screenShowXY(' ', ballX, ballY);

// if the ball goes off the screen left or right:
if ((ballX == LEFT) || (ballX == RIGHT)) {
playMiss();
// reset the ball:
ballX = WIDTH/2;
;
ballY = HEIGHT/2;
// pause  and note the time you paused:
gamePaused = true;
timeStamp = millis();
}
// increment the ball's position in both directions:
ballX = ballX + ballDirectionX;
ballY = ballY + ballDirectionY;

// if the game isn't paused, set the ball
// in its new position:
if (!gamePaused) {
// set the new position:
screenShowXY(BALL, ballX, ballY);
}
}

{
{
}
}

void playSound(int period ){
digitalWrite(BUZZER_PIN,HIGH);
delayMicroseconds(period);
digitalWrite(BUZZER_PIN, LOW);
delayMicroseconds(period);
}

void playMiss(){
for(int i=0; i < 100; i++)
playSound(400);
for(int i=0; i < 100; i++)
playSound(3000 + i);
}

// TellyMate helper functions

void screenShowXY( char ch, int x, int y){
// display the given character at the screen x and y location
cursor_move(y,x);
Serial.print(ch);
}
void screen_clear( void )
{ // <ESC>E
Serial.print( CHAR_ESC "E" );
}

void cursor_move( uint8_t row , uint8_t col )
{ // <ESC>Yrc
Serial.print( CHAR_ESC "Y" ) ;
Serial.print((unsigned char)(32 + row)) ;
Serial.print((unsigned char)(32 + col)) ;
}

void cursor_show( bool show )
{ // <ESC>e or <ESC>f
Serial.print( CHAR_ESC ) ;
Serial.print( show?'e':'f' ) ;
}
``````

Nice. I'll give that a try some time this week when I get a chance.