xxxxxxxxxx
547
// This began as...
// Spring
// by REAS <http://www.groupc.net>
// and became...
// testMOD97
// which sprouted into threebits03
// mangled by oz
// Hey, if this mess of code works, think what a decent programmer could do
// Updated 24 NOV 03
// Updated to p5js on 21 July 2024
// to become a demonstration of secondary emission of electrons
// as background history for The RCA Selectron digital memory tube
// Pulse the backplate and enable cathodes to write data to the eyelets
// Spring drawing constants for eyelet motion
let s_height = 10; // Height
let left = 60; // Left position
let right = 103; // Right position
let max = 250; // Maximum Y value
let min = 152; // Minimum Y value
let writeok = true; // OK to initiate write pulse
let over10 = false; // If mouse over
let over11 = false; // If mouse over
let over20 = false; // If mouse over
let over21 = false; // If mouse over
let over30 = false; // If mouse over
let over31 = false; // If mouse over
let move = false; // If mouse down and over
let charge1 = 30; // Initial charge on eyelet
let charge2 = 30; // Initial charge on eyelet
let charge3 = 30; // Initial charge on eyelet
let size = 5; // Width of the shape
let xpos; // Position of electrons
let ypos1; // Position of electrons
let ypos2; // Position of electrons
let ypos3; // Position of electrons
let beamon1 = false; // Enable cathode emission
let beamon2 = true; // Enable cathode emission
let beamon3 = true; // Enable cathode emission
let ringer1; // Position of the electron which can succeed
let ringer2; // Position of the electron which can succeed
let ringer3; // Position of the electron which can succeed
let yspeed1 = 10; // Speed of the electrons
let yspeed2 = 10; // Speed of the electrons
let yspeed3 = 10; // Speed of the electrons
let ydirection1 = 1; // Top to Bottom
let ydirection2 = 1; // Top to Bottom
let ydirection3 = 1; // Top to Bottom
let ringerdir1 = 1; // Top to Bottom of the lone electron
let ringerdir2 = 1; // Top to Bottom of the lone electron
let ringerdir3 = 1; // Top to Bottom of the lone electron
let drift1 = 0; // Deflected electron lateral movement
let drift2 = 0; // Deflected electron lateral movement
let drift3 = 0; // Deflected electron lateral movement
let level1 = 0; // Top of the heap
let level2 = 0; // Top of the heap
let level3 = 0; // Top of the heap
let twins1 = 1; // secondary electron display enable
let twins2 = 1; // secondary electron display enable
let twins3 = 1; // secondary electron display enable
// Spring simulation constants
let M = 0.8; // Mass
let K = 0.2; // Spring constant
let D = 0.05; // Damping
let R = 200; // Rest position
// Spring simulation variables
let ps = 200.0; // Position
let vs = 0.0; // Velocity
let as = 0; // Acceleration
let f = 0; // Force
// BFont metaItalic;
// The font "Meta-Italic.vlw.gz" must be located in the
// current sketch's "data" directory to load successfully
function setup() {
createCanvas(500, 380);
rectMode(CORNERS);
noStroke();
colorMode(RGB);
frameRate(30);
textSize(16);
// metaItalic = loadFont("Meta-Italic.vlw.gz");
// Set the starting position of the electron beam
xpos = 75;
ypos1 = 60;
ringer1 = 60;
ypos2 = 60;
ringer2 = 60;
ypos3 = 60;
ringer3 = 60;
// textFont(metaItalic, 20);
}
function draw()
{
background(102);
updateEyelet();
drawEyelet();
// border
fill (0);
rect (0,0,2,380);
rect (0,0,500,2);
rect (500,380,0,378);
rect (500,380,498,0);
// buttons
if ( over10 && writeok ){
fill(255);
}
rect (360,150,380,170);
fill (0);
if ( over11 && writeok ){
fill(255);
}
rect (360,210,380,230);
fill (0);
if ( over20 && writeok ){
fill(255);
}
rect (400,150,420,170);
fill (0);
if ( over21 && writeok ){
fill(255);
}
rect (400,210,420,230);
fill (0);
if ( over30 && writeok ){
fill(255);
}
rect (440,150,460,170);
fill (0);
if ( over31 && writeok ){
fill(255);
}
rect (440,210,460,230);
// Collectors are gray
// fill(70,70,70);
// rect(xpos + 25, 40, xpos + 90, 50);
// rect(xpos + 125, 40, xpos + 190, 50);
// rect(xpos + 225, 40, xpos + 290, 50);
// Hot Cathodes are red
fill(70,70,70);
if (beamon1) {
fill(200,75,30);
}
rect(xpos + 15, 40, xpos, 50);
fill(70,70,70);
if (beamon2) {
fill(200,75,30);
}
rect(xpos + 115, 40, xpos + 100, 50);
fill(70,70,70);
if (beamon3) {
fill(200,75,30);
}
rect(xpos + 215, 40, xpos + 200, 50);
// Text
fill(255,255,255);
text("Selective Writing", 360, 373);
text("cathodes", 380,50);
if ( writeok ){
text("pulse set", 382, 250);
text("pulse clear", 375, 135);
}
// Electrons are blue...right?
fill(20,200,200);
// Above this level, lower potential, electrons are repelled
rect(right + 5, 150,right + 15, 151);
// Below this level, higher potential, secondary electrons are ejected
rect(right + 5, 180,right + 15, 181);
// Update the position of the electron beam
ypos1 = ypos1 + (yspeed1 * ydirection1);
ringer1 = ringer1 + (yspeed1 * ringerdir1);
level1 = (ps + 5 - charge1 - ypos1);
ypos2 = ypos2 + (yspeed2 * ydirection2);
ringer2 = ringer2 + (yspeed2 * ringerdir2);
level2 = (ps + 5 - charge2 - ypos2);
ypos3 = ypos3 + (yspeed3 * ydirection3);
ringer3 = ringer3 + (yspeed3 * ringerdir3);
level3 = (ps + 5 - charge3 - ypos3);
// Blast out secondaries if charge is low (delta potential high)
if (ps - charge1 > 180 && ypos1 > ps - 5 - charge1) {
ydirection1 = -1;
ringerdir1 = -1;
charge1 = charge1 - 8;
yspeed1 = 10;
drift1 = -.3;
twins1 = 0.5;
}
if (ps - charge2 > 180 && ypos2 > ps - 5 - charge2) {
ydirection2 = -1;
ringerdir2 = -1;
charge2 = charge2 - 8;
yspeed2 = 10;
drift2 = -.3;
twins2 = 0.5;
}
if (ps - charge3 > 180 && ypos3 > ps - 5 - charge3) {
ydirection3 = -1;
ringerdir3 = -1;
charge3 = charge3 - 8;
yspeed3 = 10;
drift3 = -.3;
twins3 = 0.5;
}
// Let the lone electron pass
if ((charge1 < 2) && (ypos1 > 180)) {
ringerdir1 = 1;
}
if ((charge2 < 2) && (ypos2 > 180)) {
ringerdir2 = 1;
}
if ((charge3 < 2) && (ypos3 > 180)) {
ringerdir3 = 1;
}
// Hey, this ain't a Van de Graaff -- leakage exists
if (charge1 < 0) {
charge1 = 0;
}
if (charge2 < 0) {
charge2 = 0;
}
if (charge3 < 0) {
charge3 = 0;
}
// repel if fully charged
// (charge) && (touch: where repelled)
if ( ((ps - charge1 ) <155) && ypos1 > ps - 15 - charge1) {
ydirection1 = -1;
ringerdir1 = -1;
charge1 = charge1 - 2;
drift1 = -.5;
yspeed1 = 10;
}
if ( ((ps - charge2 ) <155) && ypos2 > ps - 15 - charge2) {
ydirection2 = -1;
ringerdir2 = -1;
charge2 = charge2 - 2;
drift2 = -.5;
yspeed2 = 10;
}
if ( ((ps - charge3 ) <155) && ypos3 > ps - 15 - charge3) {
ydirection3 = -1;
ringerdir3 = -1;
charge3 = charge3 - 2;
drift3 = -.5;
yspeed3 = 10;
}
//emit some electrons from the cathode, if none in play
if ((ypos1 > ps + 5 - charge1 || ypos1 < 40) && beamon1 ) {
ypos1 = 60;
ringer1 = 60;
drift1 = 0;
yspeed1 = 10;
twins1 = 1;
ydirection1 = 1;
ringerdir1 = 1;
charge1 = charge1 + 2;
}
if ((ypos2 > ps + 5 - charge2 || ypos2 < 40) && beamon2 ) {
ypos2 = 60;
ringer2 = 60;
drift2 = 0;
yspeed2 = 10;
twins2 = 1;
ydirection2 = 1;
ringerdir2 = 1;
charge2 = charge2 + 2;
}
if ((ypos3 > ps + 5 - charge3 || ypos3 < 40) && beamon3 ) {
ypos3 = 60;
ringer3 = 60;
drift3 = 0;
yspeed3 = 10;
twins3 = 1;
ydirection3 = 1;
ringerdir3 = 1;
charge3 = charge3 + 2;
}
// Let the lone electron pass
if ((charge1 < 2) && (ypos1 > 180)) {
ringerdir1 = 1;
}
if ((charge2 < 2) && (ypos2 > 180)) {
ringerdir2 = 1;
}
if ((charge3 < 2) && (ypos3 > 180)) {
ringerdir3 = 1;
}
// Draw the primary electrons
ellipse((xpos + 10) - (drift1 * level1), ypos1, 5, 5);
ellipse((xpos + 110) - (drift2 * level2), ypos2, 5, 5);
ellipse((xpos + 210) - (drift3 * level3), ypos3, 5, 5);
// And draw the secondaries -- coincident if they don't exist
ellipse((xpos + 10) - (drift1 * level1 * twins1), ypos1, 5, 5);
ellipse((xpos + 110) - (drift2 * level2 * twins2), ypos2, 5, 5);
ellipse((xpos + 210) - (drift3 * level3 * twins3), ypos3, 5, 5);
// Draw our lone secondary electron
ellipse(xpos + (drift1 * level1 * .3 * (ringerdir1 - 1)) , ringer1, 5, 5);
ellipse(xpos + 100 + (drift2 * level2 * .3 * (ringerdir2 - 1)) , ringer2, 5, 5);
ellipse(xpos + 200 + (drift3 * level3 * .3 * (ringerdir3 - 1)) , ringer3, 5, 5);
// Draw a phosphor grain.
fill(20,250 - 2 * (ringer1 - 330),20);
if (ringer1 <325 ){
fill(20,100,20);
}
ellipse(xpos -1, 320, 20, 20);
fill(20,250 - 2 * (ringer2 - 330),20);
if (ringer2 <325 ){
fill(20,100,20);
}
ellipse(xpos+95, 320, 20, 20);
fill(20,250 - 2 * (ringer3 - 330),20);
if (ringer3 <325 ){
fill(20,100,20);
}
ellipse(xpos+195, 320, 20, 20);
// enable all cathodes
if (ps < 205 && ps > 195){
beamon1 = true;
beamon2 = true;
beamon3 = true;
writeok = true;
} else {
writeok = false;
}
}
// Hey, this ain't FORTRAN ... there's no GOTO
function drawEyelet()
{
// Set color and draw eyelet and electrons
fill(0);
rect(left, ps, left + 10, ps + s_height);
rect(right - 10, ps, right, ps + s_height);
rect(left, ps - 50, left + 5, ps);
rect(right, ps - 50, right - 5, ps);
rect(left + 100, ps, left + 110, ps + s_height);
rect(right + 90, ps, right + 100, ps + s_height);
rect(left + 100, ps - 50, left + 105, ps);
rect(right + 100, ps - 50, right + 95, ps);
rect(left + 200, ps, left + 210, ps + s_height);
rect(right + 190, ps, right + 200, ps + s_height);
rect(left + 200, ps - 50, left + 205, ps);
rect(right + 200, ps - 50, right + 195, ps);
// Electrons
fill(20,200,200);
rect(left + 205, ps, right + 195, ps - charge3);
rect(left + 5, ps, right - 5, ps - charge1);
rect(left + 105, ps, right + 95, ps - charge2);
// Draw voltage divider
stroke(255);
// line(60, ps, 35, ps );
line(60, ps, 50, ps );
line(45, ps, 35, ps );
line(45, ps + 4, 45, ps - 4 );
line(50, ps + 4, 50, ps - 4 );
line(38, ps +3, 35, ps );
line(38, ps - 3, 35, ps );
line(25, 205, 20, 205);
line(25, 195, 20, 195);
beginShape(LINE_STRIP);
vertex(32, 110);
vertex(32, 137);
vertex(30, 140);
vertex(35, 145);
vertex(30, 150);
vertex(35, 155);
vertex(30, 160);
vertex(35, 165);
vertex(30, 170);
vertex(35, 175);
vertex(30, 180);
vertex(35, 185);
vertex(30, 190);
vertex(35, 195);
vertex(30, 200);
vertex(35, 205);
vertex(30, 210);
vertex(35, 215);
vertex(30, 220);
vertex(35, 225);
vertex(30, 230);
vertex(35, 235);
vertex(30, 240);
vertex(35, 245);
vertex(30, 250);
vertex(35, 255);
vertex(33, 257);
vertex(33, 280);
endShape();
text("+V", 25, 295);
text("-V", 25, 105);
noStroke();
}
function updateEyelet()
{
// Update the eyelet position
if(!move) {
f = -K * (ps - R); // f=-ky
as = f / M; // Set the acceleration, f=ma == a=f/m
vs = D * (vs + as); // Set the velocity
ps = ps + vs; // Updated position
}
if(abs(vs) < 0.1) {
vs = 0.0;
}
// Test if mouse is over
if( mouseY > 210 && mouseY < 230 && mouseX > 360 && mouseX < 380 ) {
over11 = true;
} else {
over11 = false;
}
if( mouseY > 150 && mouseY < 170 && mouseX > 360 && mouseX < 380 ) {
over10 = true;
} else {
over10 = false;
}
if( mouseY > 210 && mouseY < 230 && mouseX > 400 && mouseX < 420 ) {
over21 = true;
} else {
over21 = false;
}
if( mouseY > 150 && mouseY < 170 && mouseX > 400 && mouseX < 420 ) {
over20 = true;
} else {
over20 = false;
}
if( mouseY > 210 && mouseY < 230 && mouseX > 440 && mouseX < 460 ) {
over31 = true;
} else {
over31 = false;
}
if( mouseY > 150 && mouseY < 170 && mouseX > 440 && mouseX < 460 ) {
over30 = true;
} else {
over30 = false;
}
// Set and constrain the position of eyelet
if( move && ( over10 || over20 || over30 )){
ps = 150;
}
if( move && ( over11 || over21 || over31 )){
ps = 250;
}
// Disable the deselected cathodes
if( move && ( over11 || over10 )){
beamon2 = false;
beamon3 = false;
}
if( move && ( over21 || over20 )){
beamon1 = false;
beamon3 = false;
}
if( move && ( over31 || over30 )){
beamon1 = false;
beamon2 = false;
}
}
function mousePressed() {
if((over11 || over10 || over20 || over21 || over30 || over31 ) && writeok ) {
move = true;
}
}
function mouseReleased()
{
move = false;
}