pain
pain registers: shifting the site of execution.
two days after two minutes firefox activity
pain registers directly translates CPU activities (as changes in a common storage register named EAX, or, alternatively, the exact CPU instruction executed, the opcode) when running a chosen piece of software into the often painful inscription of a needle on the hand. pain registers successfully shifts the site of execution in homage to Kafka's "In the Penal Colony".
Modifying self3 code, pain registers uses traced register values or opcodes (delivered by way of the ptrace system call) to drive a servo, chopstick and needle apparat. As ptraced code necessarily runs much more slowly than untraced code, simply starting the firefox executable allows for over 16 hours of needle inflicted pain on the subject's skin before they are able to enjoy the fruits of the CPU labour.
pain registers is part of the data sedimentation project and will also be used within the psychogeophysics walker as a feedback mechanism.
see also: Shifting the site of execution text!
Hardware
Two Arduino-based prototypes have been designed. The first based on a simple servo and chopstick combination.
The second re-uses components of a CD-ROM drive combined with a simple L298 motor driver.
Video
The first prototype in action transcribing "ls -la" as the command:
The CDROM-based prototype with execution from firefox (opcodes and startup).
code
For the opcode version, on the PC side:
#include <stdio.h> #include <sys/ptrace.h> #include <errno.h> #include <sys/types.h> #include <sys/resource.h> #include <sys/wait.h> #include <signal.h> #include <stdlib.h> #include <lo/lo.h> #include <sys/user.h> int main (int argc, char *argv[]) { long long counter = 1; // machine instruction counter int wait_val; // child's return value int pid; // child's process id struct user_regs_struct red; unsigned int x,y,xy,ya,yb,yc,yd,ye,yf,yg,yh,yi,err,signo; unsigned char buffer[8]; int exitf=0; pid=strtoul(argv[1], NULL, 10); ptrace(PTRACE_ATTACH,pid,0,0); wait(&wait_val); if (ptrace(PTRACE_SINGLESTEP,pid,NULL,NULL) != 0) perror("ptracex:"); while(!exitf){ ptrace(PTRACE_SINGLESTEP,pid,NULL,signo); x=ptrace(PTRACE_GETREGS,pid,NULL,&red); wait(&wait_val); ya=red.eip; if (ya>0) { yb=ptrace(PTRACE_PEEKDATA,pid,ya,NULL); printf("%c",yb%255); } if ((signo = WSTOPSIG(wait_val)) == SIGTRAP) { signo = 0; } if ((signo == SIGHUP) || (signo == SIGINT)) { ptrace(PTRACE_CONT, pid, 0, signo); printf("Child took a SIGHUP or SIGINT. We are done\n"); exitf=0; break; } } }
Compiles as
gcc traceopcode.c -otraceop
and then:
./traceop PROCESSID > /dev/ttyUSB0
with simple serial to servo or motor driver (L298) code running on Arduino:
/* L298 ---> pins: - from left to right on board: 1-GND 2-supply 3-logic 4-enable->PWM 5-dir? 6-dir? 7 (far right) -> 51 - PWM2 as enable - 52 and 53 as direction (which way?) - 51 as sensing (pull high and is inverted) */ int dir1=52; int dir2=53; int sens=51; void setup() { unsigned char x=0; long lk; pinMode(dir1, OUTPUT); pinMode(dir2, OUTPUT); pinMode(2, OUTPUT); pinMode(sens, INPUT); digitalWrite(sens, HIGH); Serial.begin(9600); // zero cd-needle while (x==0){ x=digitalRead(sens); // switches when x=1; digitalWrite(dir1, HIGH); // dir2=low/1=high == IN digitalWrite(dir2, LOW); analogWrite(2, 255); // 128-255 } analogWrite(2, 0); // 128-255 } void loop() { int ll, oldll; unsigned char rr; long lll,x; rr=0; if (Serial.available() > 0) { rr = Serial.read(); } // move to char within limit! == 38000 // with new psu= half lll=(int)(rr*100); // lll=0; for (x=0;x<lll;x++){ digitalWrite(dir2, HIGH); // dir2=low/1=high == IN digitalWrite(dir1, LOW); // digitalWrite(2,HIGH); analogWrite(2, 255); // 128-255 } analogWrite(2, 0); // 128-255 // back up till HIT! x=0; while (x==0){ x=digitalRead(sens); // switches when x=1; digitalWrite(dir1, HIGH); // dir2=low/1=high == IN digitalWrite(dir2, LOW); analogWrite(2, 255); // 128-255 } }
/* one SERVO */ #include <MegaServo.h> #define NBR_SERVOS 1 // the number of servos, up to 48 for Mega, 12 for other boards #define FIRST_SERVO_PIN 2 MegaServo Servos[NBR_SERVOS] ; // max servos is 48 for mega, 12 for other boards int pos = 0; // variable to store the servo position int potPin = 0; // connect a pot to this pin. void setup() { Serial.begin(9600); for( int i =0; i < NBR_SERVOS; i++) Servos[i].attach( FIRST_SERVO_PIN +i, 800, 2200); } void loop() { pos=pos%148; // adjust for fingers if (Serial.available() > 0) { // read the incoming byte: pos = (100+(Serial.read()%80)); } for( int i =0; i <NBR_SERVOS; i++) Servos[i].write(pos); delay(1); }
Date: 2013-04-23 17:14:40 BST
HTML generated by org-mode 6.31trans in emacs 23