Interface and Application Programming

This week I will create an interface and app that uses my input device

software / sites used during this week

X-Code
XCode editor I will use to programm my attiny
Atom editor
Atom editor I used for woring with my nodeJS app
Kivy
Python based graphic interface design and application software.
NodeJS
JS server side software (I used it with libraries)
Pong node-js
I took for example the pong application from github and modified it to use with my input device (lack of time to write my own)

hardware

Attiny 44
Attiny 44 with my input board and ftdi cable

All files that I have demonstrated below are also available in this zip file

Programming input device

My input device need to recognize the touch panel I touched and return me just this panel ID. Instead of values that I saw when I worked with input devices I need just an ID and the logic of recognition which panel in touch need to be moved to the attiny side. So I will define the threshold and if my value is lower then threshold - I will return the ID of sensor instead of value.



                          #include <avr/io.h>
                          #include <util/delay.h>

                          #define output(directions,pin) (directions |= pin) // set port direction for output
                          #define set(port,pin) (port |= pin) // set port pin
                          #define clear(port,pin) (port &= (~pin)) // clear port pin
                          #define pin_test(pins,pin) (pins & pin) // test for port pin
                          #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
                          #define bit_delay_time 100 // bit delay for 9600 with overhead
                          #define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
                          #define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay
                          #define charge_delay_1() _delay_us(1) // charge delay 1
                          #define charge_delay_2() _delay_us(10) // charge delay 2
                          #define charge_delay_3() _delay_us(100) // charge delay 3
                          #define settle_delay() _delay_us(100) // settle delay
                          #define char_delay() _delay_ms(10) // char delay
                          #define ref (0 << REFS1) | (0 << REFS0) // reference voltage

                          #define serial_port PORTB
                          #define serial_direction DDRB
                          #define serial_pin_out (1 << PB1)
                          #define charge_port PORTA
                          #define charge_direction DDRA
                          #define charge_pin (1 << PA3)

                          #define sense0 (0 << MUX2) | (0 << MUX1) | (0 << MUX0) // PA0
                          #define sense1 (0 << MUX2) | (0 << MUX1) | (1 << MUX0) // PA1
                          #define sense2 (0 << MUX2) | (1 << MUX1) | (0 << MUX0) // PA2

                          /*

                           VCC     GND
                           (PCINT8/XTAL1/CLKI)             PB0     PA0 (ADC0/AREF/PCINT0)       - sense0
                           (PCINT9/XTAL2)                  PB1     PA1 (ADC1/AIN0/PCINT1)       - sense1
                           (PCINT11/RESET/dW)              PB3     PA2 (ADC2/AIN1/PCINT2)       - sense2
                           (PCINT10/INT0/OC0A/CKOUT)       PB2     PA3 (ADC3/T0/PCINT3)
                           (PCINT7/ICP/OC0B/ADC7)          PA7     PA4 (ADC4/USCK/SCL/T1/PCINT4)
                           (PCINT6/OC1A/SDA/MOSI/DI/ADC6)  PA6     PA5 (ADC5/DO/MISO/OC1B/PCINT5)
                           */

                          // GIMSK:   - INT0 PCIE1 PCIE0 - - - -
                          // PCMSK1:  - - - - PCINT11 PCINT10 PCINT9 PCINT8
                          // PCMSK0:  PCINT7 PCINT6 PCINT7 PCINT4 PCINT3 PCINT2 PCINT1 PCINT0

                          #define threshold 750

                          void put_char(volatile unsigned char *port, unsigned char pin, char txchar) {
                              //
                              // send character in txchar on port pin
                              //    assumes line driver (inverts bits)
                              //
                              // start bit
                              //
                              clear(*port,pin);
                              bit_delay();
                              //
                              // unrolled loop to write data bits
                              //
                              if bit_test(txchar,0)
                                  set(*port,pin);
                              else
                                  clear(*port,pin);
                              bit_delay();
                              if bit_test(txchar,1)
                                  set(*port,pin);
                              else
                                  clear(*port,pin);
                              bit_delay();
                              if bit_test(txchar,2)
                                  set(*port,pin);
                              else
                                  clear(*port,pin);
                              bit_delay();
                              if bit_test(txchar,3)
                                  set(*port,pin);
                              else
                                  clear(*port,pin);
                              bit_delay();
                              if bit_test(txchar,4)
                                  set(*port,pin);
                              else
                                  clear(*port,pin);
                              bit_delay();
                              if bit_test(txchar,5)
                                  set(*port,pin);
                              else
                                  clear(*port,pin);
                              bit_delay();
                              if bit_test(txchar,6)
                                  set(*port,pin);
                              else
                                  clear(*port,pin);
                              bit_delay();
                              if bit_test(txchar,7)
                                  set(*port,pin);
                              else
                                  clear(*port,pin);
                              bit_delay();
                              //
                              // stop bit
                              //
                              set(*port,pin);
                              bit_delay();
                              //
                              // char delay
                              //
                              bit_delay();
                          }

                          int check_sensor(unsigned char pin) {
                              unsigned char up_lo,up_hi,down_lo,down_hi;
                              int up_value, down_value, value;

                              ADMUX = ref | pin;

                              settle_delay();
                              set(charge_port, charge_pin);
                              charge_delay_1();

                              ADCSRA |= (1 << ADSC);
                              while (ADCSRA & (1 << ADSC))
                                  ;

                              up_lo = ADCL;
                              up_hi = ADCH;

                              settle_delay();
                              clear(charge_port, charge_pin);
                              charge_delay_1();

                              ADCSRA |= (1 << ADSC);

                              while (ADCSRA & (1 << ADSC))
                                  ;

                              down_lo = ADCL;
                              down_hi = ADCH;

                              up_value = 256 * up_hi + up_lo;
                              down_value = 256 * down_hi + down_lo;
                              value = (up_value + (1023 - down_value)) / 2;
                              return threshold - value <= 0 ? 0 : threshold - value;
                          }

                          void print_int(int value) {
                              char str[4] = "    ";
                              itoa(value, str, 10);
                              int i;
                              for(i=0; i<4; i++)
                              {
                                  put_char(&serial_port, serial_pin_out, str[i]);
                                  char_delay();
                              }
                          }

                          int main(void) {

                              //
                              // main
                              //
                              //
                              // set clock divider to /1
                              //
                              CLKPR = (1 << CLKPCE);
                              CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
                              //
                              // initialize output pins
                              //
                              set(serial_port, serial_pin_out);
                              output(serial_direction, serial_pin_out);
                              clear(charge_port, charge_pin);
                              output(charge_direction, charge_pin);
                              //
                              // init A/D
                              //
                              ADMUX = ref; // Vcc ref
                              ADCSRA = (1 << ADEN) // enable
                              | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128
                              ADCSRB = (0 << ADLAR); // right adjust

                              int measurements[8];
                              //
                              // main loop
                              //
                              while (1) {

                                  int centroid = 0;
                                  int  sum = 0;
                                  //
                                  // sense pins
                                  //
                                  measurements[0] = check_sensor(sense0);
                                  measurements[1] = check_sensor(sense1);
                                  measurements[2] = check_sensor(sense2);
                                  int i;
                                  for(i = 0; i<3; i++) {
                                      sum += measurements[i];
                                      centroid += i*measurements[i];
                                  }
                                  centroid = centroid*10 / sum;
                                  if(sum > 0)
                                  {
                                      print_int(centroid);
                                      put_char(&serial_port, serial_pin_out, '\r');
                                      char_delay();
                                      put_char(&serial_port, serial_pin_out, '\n');
                                      char_delay();
                                  }
                              }
                          }
                        

And below is the simple code of the nodeJS server that just receive clicks and show them. I send 0 10 20 as ID (for future purposes)

                          
                            var serialport = require("serialport");
                            var SerialPort = serialport.SerialPort;

                            var serialPort = new SerialPort("/dev/cu.usbserial-FTFP79MY", {
                              baudrate: 9600,
                              parser: serialport.parsers.readline("\n")
                            });

                            serialPort.on("open", function () {
                              console.log('open');
                              serialPort.on('data', function(data) {
                                console.log(data);
                              });
                            });
                          
                        

So we can see how it works.

Programming application

Now let integrate the code inside the application. What I need is to define functions to my keys on my input device and use them in the code. Let check this out.

I will use the socket to transfer information. (not the best way in real application of such case, but good as example). So below is the integration of the sending keys. I wrapped the socket into the serial connection. So socket will be opened only when the serial port is present and opened. So on each click on touchpad it send key 'up' / 'down' or 'space'

                          
                            serialPort.on('open', function () {

                            io.sockets.on('connection', function (socket) {

                                serialPort.on('data', function(pushed) {
                                  pushed = pushed.replace(/(\r\n|\n|\r|\s)/gm,"");
                                  if(pushed[0] == 0){
                                    socket.emit('key', 'up');
                                  } else if(pushed[0] == 1){
                                    socket.emit('key', 'space');
                                  } else if(pushed[0] == 2){
                                    socket.emit('key', 'down');
                                  }

                                });
                          
                        

and later in code where we process the keys I added following code to react on received messages

                          
                            socket.on('key', function(pressed){
                            console.log(pressed);
                            if(pressed == 'down'){
                              shape_movement_timer = setInterval(function() {
                                if(shape.can_move({to: 'bottom'})) {
                                  shape.move({to: 'bottom'});
                                  redraw_all();
                                }
                              }, TICK_INTERVAL);
                            } else if (pressed == 'up'){
                              shape_movement_timer = setInterval(function() {
                                if(shape.can_move({to: 'top'})) {
                                  shape.move({to: 'top'});
                                  redraw_all();
                                }
                              }, TICK_INTERVAL);
                            } else if (pressed == 'space'){
                              if(current_player_id == player_id_having_the_ball && round_could_be_started) {
                                start_round();
                                var coords = ball.get_coordinates();
                                socket.json.emit('round_started', {room_id: window.room_id, ball_x: coords.ball_x, ball_y: coords.ball_y});
                              }
                            }
                          });
                          
                        

Let see how it works! :-) I open two browser and I use one my control panel to start the game and to move rockets :-)