Wednesday 30 September 2015

The Recreated ZX Spectrum


Just a quick note on the Recreated ZX Spectrum retro Bluetooth/USB keyboard.

Appearance

The designers have done a good job making the Recreated look almost exactly like a real Spectrum. Even the rubber feet and faux-heatsink holes are in a correct position. Obviously the backside is different from the original, because it's not a computer and does not have Spectrum connectors.

The inevitable comparison
On the surface, there are very minor differences. The Sinclair ZX Spectrum logo is embossed a bit taller and the angle for the elevated back is a bit different. I have to appreciate they did not add any "recreated" or other new logos on the device. Maybe, just maybe, the metal panel bends ever so slightly due to the way it has been connected.

Having said that, it really looks like a Speccy. To me the surface matting, paint glossiness, key graphics - all are ok. It would be unfair to nitpick on the differences.


But how does it feel? It's not as heavy as the original, but the perfectionist might correct this by inserting some weights inside. (The case is held together by screws). The keyboard feels quite as it should, maybe the touch is just a tiny bit lighter. Am I imagining the keys have more tendency to bend at an angle when you press them? Acoustically, the key presses sound a bit sharper and have more "echo" to them.

The keyboard is pretty much as atrocious as the original, which is a compliment here. It remains to be seen how much I can get used to it. I tried to type some of this blog post with the Recreated, but gave up after a paragraph.

Functionality

The Recreated is mainly intended to work with the Elite Systems' Spectrum app on the iOS appstore. My interest is in getting it to work with a PC, so I've not even tried the app.

A lot of effort has gone into enabling the keyboard to work on iOS devices both as a keyboard and a gamepad (not only for the Spectrum app) and as a normal PC-keyboard. However this means that at least currently it won't work directly in emulators as a 100% Spectrum-equivalent keyboard. For example, getting the " character does not result from pressing Symbol Shift+P, as it is mapped to shift+2. Perhaps if emulator makers accommodate, the Recreated will be a slightly better deal in this respect.

I was worried the keyboard might not work without batteries, but the included USB cable is sufficient, and I prefer this to wireless. Obviously the Bluetooth is the way to go with mobile devices.

One unexpected thing was the "unlocking" procedure, which you have to do to get the device to work properly as a keyboard. This is easily done online at the Elite systems website or through the app, but still to me this felt a bit of an added rigmarole. Fortunately the device appears to remember the setting.

Sorry about the weird angle but I was not going to dismantle it more for the time being.
Looking inside, there's a lot of free space. The battery holder means the case is not that easy to mod into a real Spectrum case, but it might be within the realms of possibility. Note though the keyboard membrane cables are different and come out from different places. Interestingly the designers have preserved the 5/8 (5/10 really) division and possibly the original membrane matrix. The usual RWAP replacement membranes probably cannot be used here.

Addendum: I checked if the plastic pieces are interchangeable with old Spectrum case parts. I found the Recreated bottom and old Spectrum top fit together somewhat ok, but not the other way round. The changes required could be minimal, though. This, of course, without the PCB inside. 

So, the situation is fairly good for projects that combine the Recreated keyboard with an old computer. 

An old PCB does not fit well inside the Recreated bottom, even if the battery holders were removed. There's a specific groove for the PCB in the real Spectrum case which does not exist in the Recreated. 
The red arrow points to the lacking PCB groove.
An Arduino fits inside without any changes, using low or bent cables for the I/O pins. A Raspberry Pi could just about fit there, if the battery holder is removed and care is taken in positioning the board.

All in all

If someone has decided to limit their Speccy-activities and game playing on a mobile device, the app+Recreated might be good combo. Text adventures and complex games are really crying for a keyboard anyway.

For a more involved retro hobbyist like me, it's harder to pinpoint a really good use. I have my real Speccies, and emulators do not greatly benefit from this keyboard because of the key mapping. It could have been nice for a bit of BASIC programming. It's kind of fun for games, though. I would like to connect it to my ZX Evolution, but it's a no-go because the Evo uses PS/2 keyboards.

A Kempston/Atari joystick connector would have added more value to this, but admittedly it's a bit hard to see how it could work in a simple way. Cursor emulation?

The ZX Spectrum Recreated might be expensive, I maybe paid more for this than on any single retro computer I've bought (but then I'm a cheapskate) but I suppose that's not a major issue. It's not much more expensive than many specialist keyboards, although I'll have to repeat a ZX Spectrum keyboard, recreated or not, doesn't really work as a good PC keyboard replacement.

I'm positive about the product in the sense that this might mean more real ZX Spectrums in the future, now that there is a precedent for manufacturing the required physical parts. Time will tell...

More info:
http://sinclair.recreatedzxspectrum.com/


Friday 11 September 2015

Line-Line intersection test

I once did some programming that required mathematical line-line intersections, and it's really something that can't always be easily found ready-made. The mathematical formulae and "theory" are readily available, but are not easily converted to practical situations.

Below I have a Processing sketch that includes the function intersection which compares two lines. Copy/paste the text below into a processing sketch window and go. Everything else outside the function is just to facilitate the demo sketch. Moving the mouse pointer around moves the other line, whereas the other line moves randomly.

It's based on a very old program so it might not be up to scratch. My previous work also returned the intersection coordinate (what I was really after), so this is clearly a simpler case.

There's always the problem that two parallel lines, even if they overlap visibly, coordinate-wise they may not intersect mathematically. For example, lines 0,0-100,0 and 50,0-150,0 do not intersect. The program below does not solve this case. I've supposed that making multiple intersection tests with suitably "jiggled" coordinates might fix this problem for some practical purposes.


Not intersecting!

Intersecting!


float [] xp=new float[8];
float [] yp=new float[8];
float [] xv=new float[8];
float [] yv=new float[8];

boolean intersection(float X1,float Y1,float X2,float Y2,float X3,float Y3,float X4,float Y4)
{

//Tests intersection between lines x1,y1-x2,y2 and x3,y3-x4,y4
//Not sure where the original formulas are from.

//The function has the practical problem that parallel lines do not intersect.
//This may be circumvented by "jiggling" the line coordinates just a bit and making two intersection tests, not implemented here

//My original function returned the intersection coordinate, this is a simplification

 float ua,ub,denom,numer;

//not sure if the following are needed really

 if(X3>X2&&X4>X2&&X3>X1&&X4>X1){return false;}
 if(X3<X2&&X4<X2&&X3<X1&&X4<X1){return false;}
 if(Y3>Y2&&Y4>Y2&&Y3>Y1&&Y4>Y1){return false;}
 if(Y3<Y2&&Y4<Y2&&Y3<Y1&&Y4<Y1){return false;}

// the proper calculations

 numer=((X4-X3)*(Y1-Y3)-(Y4-Y3)*(X1-X3));
 denom=((Y4-Y3)*(X2-X1)-(X4-X3)*(Y2-Y1));

 if(denom==0){return false;}

 ua=(numer/denom);
 numer=((X2-X1)*(Y1-Y3)-(Y2-Y1)*(X1-X3));
 ub=(numer/denom);

 if(ua==0&&ub==0){return true;}
 if(ub>0&&ub<=1&&ua>0&&ua<=1){return true;}

 return false;
}

void draw_lines(float xa1,float ya1,float xa2,float ya2,float xb1,float yb1,float xb2,float yb2)
{

  if(intersection(xa1,ya1,xa2,ya2,xb1,yb1,xb2,yb2)==true){
    stroke(255,0,0);line(xa1,ya1,xa2,ya2);line(xb1,yb1,xb2,yb2); 
  }else
  {
    stroke(0,255,0);line(xa1,ya1,xa2,ya2);line(xb1,yb1,xb2,yb2);
  }
}

void setup()
{
  size(512,512);
  strokeWeight(2);
  xp[0]=16;yp[0]=16;xp[1]=64;yp[1]=64;
  xv[0]=2;yv[0]=1;
  xv[1]=-3;yv[1]=-1;
  xp[2]=width/2;yp[2]=height/2;xp[3]=width/2;yp[3]=height/2;
}

void mousePressed()
{
  xp[2]=mouseX;yp[2]=mouseY;
}

void draw()
{
  background(0,0,128);
  draw_lines(xp[0],yp[0],xp[1],yp[1],xp[2],yp[2],xp[3],yp[3]);
  for(int i=0;i<=7;i++){
   xp[i]=xp[i]+xv[i];
   yp[i]=yp[i]+yv[i];
   if(xp[i]>=width){xv[i]=-(1+random(2));}
   if(xp[i]<=0){xv[i]=1+random(2);}
   if(yp[i]>=height){yv[i]=-(1+random(2));}
   if(yp[i]<=0){yv[i]=1+random(2);}
  }

  xp[3]=mouseX;
  yp[3]=mouseY;
}