PC Programm

// The is the current test program for the Arduino throttle
// LocoClass
/*  Copyright (C) 2009 Michael Blank

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, see .
*/
import processing.serial.*;

Serial ThrottlePort;  // Create object from Serial class
String ThrottlePortName = "COM4";

Serial LenzPort;      // The serial port for LENZ interface
String LenzPortName ="COM2";

boolean debug = true;

LocoClass l1 = new LocoClass(7411,128); //address, speedsteps

// some variables
int val;   // Data received from the serial port
String myString= null;
int lf=10; // linefeed in ascii
int count=0;
int speed=0;
PFont fontA;

// graphics window size
int sizeX=400;  
int sizeY=100;
int offsetX=100;


void setup() {
  // init part of this program
  smooth();
  size(sizeX,sizeY);
  // frameRate(10);
  fontA = loadFont("CourierNew36.vlw");
  ThrottlePort = new Serial(this, ThrottlePortName, 9600);
  LenzPort = new Serial(this, LenzPortName, 19200);
  
}

void draw() {
  // endless loop of the program
  while (ThrottlePort.available() > 0) {
    // data from throttle (like "T1S99VF1000", terminated with cr/lf
    myString = ThrottlePort.readStringUntil(lf);
    if (myString != null) {
         if (myString.indexOf('V') != -1) {
            // forward direction ("vorwaerts")
            l1.set_dir(1);
         }  else {
            l1.set_dir(0);
         }
         String b[]=myString.split("[TSVRF]");
         if (debug) { println("/S:"+b[2]+"/F:"+b[4].substring(0,4)+"/ "); }
         speed=Integer.parseInt(b[2]);
         l1.set_funct(b[4]);
         l1.set_speed(speed);
         l1.graphics_update();
         l1.send_loco_cmd();
         l1.send_loco_func_cmd();
    }
    while (LenzPort.available() > 0) {
       // read response from Lenz interface, just for 
       // debugging / understanding
       int inByte = LenzPort.read();
       print("L"+inByte+" ");
    }
  }
}  // end of endess loop


void keyPressed() {
   if (key == ESC) {
      key = 0;  // Fools! don't let them escape!
   }
}

// Class with all info, commands etc for controlling a loco
class LocoClass  {

  int adr, speed, steps;
  int AH; // highbyte of address
  int AL; // lowbyte of address
  int func[] = { 0,0,0,0  }; //F0 ... F3
  int dir=0;  //direction
  
  boolean funcs_init=false;  // flag fuer init der funktionen

  // constructor, calc DCC address bytes 
  LocoClass (int a, int s) {  
    adr = a; 
    AH = (( a & 0xFF00) >> 8) + 0xC0;
    AL = a & 0xFF;
    steps = s; 
  } 
  
  void send_loco_cmd()  {
     // implemented only for 128 speed steps
     if ( (speed <0) || (speed >127)) {  
        //input from throttle always in this range
        println("error in speed setting");
        speed = 0;
     }
     // build command message for loco speed
     int msg[]={228,19,AH,AL,speed,0};
     if (dir == 1)  {msg[4] += 128;}
     // calc XOR
     msg[5]= 0xFF & ( ( ( (msg[0] ^ msg[1]) ^ msg[2]) ^ msg[3] ) ^ msg[4] );
     // send msg to LENZ
     for (int i=0;i