OrganProject

Check-in [0b63f0d802]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the schematics and datasheets for the LED control
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA1:0b63f0d802c43f7dc8f66f86b8d8016d6a861b22
User & Date: 200002852 2009-09-05 17:11:06
Context
2009-09-05
17:11
Add the schematics and datasheets for the LED control Leaf check-in: 0b63f0d802 user: 200002852 tags: trunk
2009-09-01
02:48
System integration to card reader. Reallocated pins for a more sensible layout on the RBBB in the card reader. Changed LED timings to reflect the hypothesis that there are two distinct clock phases, not a quadrature signal. Changed terminal code to pull the PS/2 connector pins actively HIGH momentarily before attaching a pullup resistor. This makes a cleaner transition on the cable and avoids spurious interrupts at the LED controller. check-in: 95f796cc4d user: 200002852 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added ledcontrol/LED-83.pdf.

cannot compute difference between binary files

Added ledcontrol/RBBB_Instructions_06.pdf.

cannot compute difference between binary files

Changes to ledcontrol/ledcontrol.pde.

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601



602
603


604
605
606
607
608
609
610
611
612
...
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
...
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711

712
713
714















715
716
717
718
719
720
721
722
723
724
725
726
727













728
729
730
731
732
733
734
/*
 ******************************************************************************
 *                                                                            *
 *			LED SYSTEM					      *
 *                                                                            *
 ******************************************************************************/

#define LED_CARD_PRESENT_PIN   18 /* Row 12 of card = 'card present' */
#define LED_PH1_PIN	       10 /* Row 8 of card = clock phase 1 */
#define LED_PH2_PIN	       9 /* Row 9 of card = clock phase 2 */
#define LED_COUNT 	       10 /* Number of LEDs being controlled */

#define LED_CLOCK_PERIOD_MS     6 /* Number of milliseconds per clock
				   * period (four clock periods per data
				   * byte) */

/* PROGRAM MEMORY */

const byte ledPins[] PROGMEM = {
  17, 16, 15, 14, 13, 12, 11,	/* 7 data bits */
  LED_PH2_PIN, LED_PH1_PIN,	/* 2 clock bits */
  LED_CARD_PRESENT_PIN		/* Card present */
};
#define LED_PH1_INDEX	8
#define LED_PH2_INDEX   7

enum LedState {
................................................................................
  byte i;
  switch(cpState) {
  case CP_IDLE:
    break;
  case CP_TEST:
    break;
  case CP_STOP:
    Serial.print("Saw "); Serial.print(cpWaveIndex, DEC);
    Serial.println(" bytes of wavetable.");
    if (cpWaveIndex != WAVETABLE_LEN) {
      cpState = CP_IDLE;		/* Wavetable too short */
    } else {
      for (i = 0; i < WAVETABLE_LEN; ++i) {
	wavetable[i] = cpWavetable[i];
      }
      ledSetStop();
    }
    break;
  case CP_WAKE:
    Serial.println("Should wake up here."); break;



  case CP_ZLEEP:
    Serial.println("Should zleep here."); break;


  default:
    Serial.println("Unrecognized command."); break;
  }
  cpState = CP_IDLE;
}
 
/*
 *-----------------------------------------------------------------------------
 *
................................................................................

void
cpPoll(void)
{
  byte b;

  if (ps2GetByte(&b)) {
    Serial.print(b, BYTE);
    if (b == '\n') {
      cpAction();
    } else if (cpState == CP_STOP) {
      cpAccumStop(b);
    } else if (cpState == CP_IDLE) {
      switch (b) {
      case 'T': 
................................................................................
      default:
	cpState = CP_ERROR;
	break;
      }
      cpTimer = now;
    }
  } else if (ps2LastError) {
    /* Ignore comm errors for now */
    Serial.print("\nGot error: ");
    Serial.print((int) ps2LastError, HEX);
    Serial.print(" byte=");
    Serial.println((int)b, HEX);
    cpState = CP_IDLE;
  } else if (cpState != CP_IDLE && now > cpTimer + CP_COMMAND_TIME_LIMIT) {
    Serial.println("\nCommand timed out.");

    cpState = CP_IDLE;
  }
}
















void
setup(void)
{
  now = millis();
  Serial.begin(9600);
  ps2Init();
  delay(5);
  interrupts();
  cpInit();
  ledInit();
}















void
loop(void)
{
  now = millis();
  cpPoll();
  ledPoll();







|
|
|









|







 







<
<










|
>
>
>

<
>
>

|







 







<







 







|
<
<
<
<


<
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





<






|
>
>
>
>
>
>
>
>
>
>
>
>
>







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
...
582
583
584
585
586
587
588


589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
...
671
672
673
674
675
676
677

678
679
680
681
682
683
684
...
698
699
700
701
702
703
704
705




706
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
/*
 ******************************************************************************
 *                                                                            *
 *			LED SYSTEM					      *
 *                                                                            *
 ******************************************************************************/

#define LED_CARD_PRESENT_PIN    9 /* Row 12 of card = 'card present' */
#define LED_PH1_PIN	       17 /* Row 8 of card = clock phase 1 */
#define LED_PH2_PIN	       18 /* Row 9 of card = clock phase 2 */
#define LED_COUNT 	       10 /* Number of LEDs being controlled */

#define LED_CLOCK_PERIOD_MS     6 /* Number of milliseconds per clock
				   * period (four clock periods per data
				   * byte) */

/* PROGRAM MEMORY */

const byte ledPins[] PROGMEM = {
  10, 11, 12, 13, 14, 15, 16,	/* 7 data bits */
  LED_PH2_PIN, LED_PH1_PIN,	/* 2 clock bits */
  LED_CARD_PRESENT_PIN		/* Card present */
};
#define LED_PH1_INDEX	8
#define LED_PH2_INDEX   7

enum LedState {
................................................................................
  byte i;
  switch(cpState) {
  case CP_IDLE:
    break;
  case CP_TEST:
    break;
  case CP_STOP:


    if (cpWaveIndex != WAVETABLE_LEN) {
      cpState = CP_IDLE;		/* Wavetable too short */
    } else {
      for (i = 0; i < WAVETABLE_LEN; ++i) {
	wavetable[i] = cpWavetable[i];
      }
      ledSetStop();
    }
    break;
  case CP_WAKE:
    ledWake();			/* Turn the lights on when active */
    delay(2000);		/* Delay to let the organ synchronize before
				 * trying to run a virtual card. */
    break;
  case CP_ZLEEP:

    ledZleep();			/* Turn lights off when inactive */
    break;
  default:
    break;			/* Ignore unrecognized commands */
  }
  cpState = CP_IDLE;
}
 
/*
 *-----------------------------------------------------------------------------
 *
................................................................................

void
cpPoll(void)
{
  byte b;

  if (ps2GetByte(&b)) {

    if (b == '\n') {
      cpAction();
    } else if (cpState == CP_STOP) {
      cpAccumStop(b);
    } else if (cpState == CP_IDLE) {
      switch (b) {
      case 'T': 
................................................................................
      default:
	cpState = CP_ERROR;
	break;
      }
      cpTimer = now;
    }
  } else if (ps2LastError) {
    /* Comm errors abort the command in progress */




    cpState = CP_IDLE;
  } else if (cpState != CP_IDLE && now > cpTimer + CP_COMMAND_TIME_LIMIT) {

    /* Timeout aborts the command in progress */
    cpState = CP_IDLE;
  }
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * setup --
 *
 *	Initializes the LED controller
 *
 * This function initializes the PS/2 keyboard port, delays a few milliseconds
 * for things to settle, then turns on interrupts to start handling incoming
 * characters.  It then initializes the command processor and turns on the
 * LEDs.
 *
 *-----------------------------------------------------------------------------
 */

void
setup(void)
{
  now = millis();

  ps2Init();
  delay(5);
  interrupts();
  cpInit();
  ledInit();
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * loop --
 *
 *	Main scan loop for the LED controller.
 *
 * This function reads the clock, asks the command processor to poll
 * for incoming characters (and process them as they appear), and
 * checks for whether it's time to change the LED state.
 *
 *-----------------------------------------------------------------------------
 */

void
loop(void)
{
  now = millis();
  cpPoll();
  ledPoll();

Added ledcontrol/ledcontrol.pdf.

cannot compute difference between binary files

Added ledcontrol/ledcontrol.sch.

cannot compute difference between binary files

Changes to terminal/terminal.pde.

910
911
912
913
914
915
916

917

918
919
920
921
922
923
924
....
1028
1029
1030
1031
1032
1033
1034




1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048




















1049
1050
1051
1052
1053
1054
1055
....
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
....
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
....
1199
1200
1201
1202
1203
1204
1205
1206













1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219














1220
1221
1222
1223
1224
1225
1226
1227
1228

1229

1230
1231
1232
1233
1234
1235
1236
1237
1238
1239













1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256

#define MENU_TIMEOUT_MILLIS 30000 
				/* Menus time out after 30 s of inactivity */

/* RAM for the menu system */

Menu* menuCurrent;		/* Current menu on display */

int menuLastKeyMillis;		/* Time the last keypress happened */

byte selectedStop[16];		/* Wavetable of the selected stop */

/* Forward function declarations */

Menu* menuSelHandler(byte);	/* Handler for menus that are just
				 * selections that dispatch to other
				 * menus */
................................................................................
 *
 *	Function called from the scan loop to manage the menu system
 *
 * This function polls the keypad, and if a key has been pressed, calls the
 * current menu's key handler to decide what to do with it.  If there is a
 * transition to another menu, it paints the next menu. It then records
 * the time at which the current action completed, for timeout processing.




 *
 *-----------------------------------------------------------------------------
 */

void
menuPoll() {
  int state;
  Menu* nextMenu;

  /* TODO - Handle timeout processing by resetting to mainMenu */

  /* Read the keypad */
  state = kpPoll();
  if (state != KP_NOKEY) {





















    if (state == KP_OCTOTHORP) {
      menuShow(&mainMenu);
    } else {
    
      /* Call the menu's key handler */
      Menu* (*keyfn)(byte) = (Menu* (*)(byte))
................................................................................
	menuShow(nextMenu);
      }
    }

    /* Wind the clock */
    menuLastKeyMillis = now;
  }

}
 
/*
 *-----------------------------------------------------------------------------
 *
 * menuSelHandler --
 *
................................................................................
/*
 *-----------------------------------------------------------------------------
 *
 * mainMenuHandler --
 *
 *	Handle keypresses at the main menu
 *
 * This procedure manages coming out of the 'standby' state if we were
 * in standby. It does quick stop programming for numeric keys, or starts
 * programming if * is pressed. (# requests a manual card read, which can
 * be done at any time that we're neither in standby nor sending a card image.)
 *
 *-----------------------------------------------------------------------------
 */
Menu*
mainMenuHandler(byte key)
{
  /* TODO - come out of standby */

  if (key <= 9) {

    /* 
     * Quick programming of stops - pull a preset from EEPROM and send
     * it to the organ.
     */
................................................................................
    }
  } else if (key == KP_ASTERISK) {
    sendToOrgan();
  }
  return &mainMenu;
}
 
/* TODO - UNSTUB THIS */














void
sendToOrgan(void) {
  int i;
  ps2SendByte('S');
  for (i = 0; i < 16; ++i) {
    ps2SendByte(pgm_read_byte(HexTable + (selectedStop[i] >> 4)));
    ps2SendByte(pgm_read_byte(HexTable + (selectedStop[i] & 0xf)));
  }
  ps2SendByte('\n');
  menuShow(menuCurrent);
}
 















void
setup() {

  kpInit();			/* Initialize the keypad */
  dispInit();			/* Initialize the display */
  ps2Init();			/* Initialize the communication port */

  now = millis();

  menuLastKeyMillis = now;

  menuShow(&mainMenu);

  {				/* TEMP - Send a comment for debugging */
    char* p;
    byte c;
    for (p = PSTR("TEST\n"); (c = pgm_read_byte(p)) != '\0'; ++p) {
      ps2SendByte(c);
    }
  }
}














void
loop() {

  now = millis();

  menuPoll();			/* Service the keyboard and display */
  ps2Poll();			/* Service the communication port */

}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 2
 * End:
 */







>
|
>







 







>
>
>
>









<
<


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







<
|








<







 







|
>
>
>
>
>
>
>
>
>
>
>
>
>













>
>
>
>
>
>
>
>
>
>
>
>
>
>








|
>
|
>
|

<
<
|
<
|
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>




|
<











910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
....
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049


1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
....
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
....
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
....
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283


1284

1285
1286
1287

1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305

1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316

#define MENU_TIMEOUT_MILLIS 30000 
				/* Menus time out after 30 s of inactivity */

/* RAM for the menu system */

Menu* menuCurrent;		/* Current menu on display */
unsigned long menuLastKeyMillis;
				/* Time the last keypress happened */
byte menuStandby;		/* 1 if the system is asleep, 0 if it's awake */
byte selectedStop[16];		/* Wavetable of the selected stop */

/* Forward function declarations */

Menu* menuSelHandler(byte);	/* Handler for menus that are just
				 * selections that dispatch to other
				 * menus */
................................................................................
 *
 *	Function called from the scan loop to manage the menu system
 *
 * This function polls the keypad, and if a key has been pressed, calls the
 * current menu's key handler to decide what to do with it.  If there is a
 * transition to another menu, it paints the next menu. It then records
 * the time at which the current action completed, for timeout processing.
 * When sufficient time elapses without a keystroke, the function drops into
 * standby by turning off the display backlight and putting the LED control
 * into standby. It returns from standby on the next keypress by turning
 * all the lights back on again.
 *
 *-----------------------------------------------------------------------------
 */

void
menuPoll() {
  int state;
  Menu* nextMenu;



  /* Read the keypad */
  state = kpPoll();
  if (state == KP_NOKEY) {

    /* Go into standby if there has been no activity for sufficiently long. */
    if ((!menuStandby) && ((now-menuLastKeyMillis) > MENU_TIMEOUT_MILLIS)) {
      ps2SendByte('Z');
      ps2SendByte('\n');
      analogWrite(DISP_BRIGHTNESS_PIN, 0);
      menuShow(&mainMenu);
      menuStandby = 1;
    }

  } else {

    /* If we were in standby, come out of standby */
    if (menuStandby) {
      ps2SendByte('W');
      ps2SendByte('\n');
      menuStandby = 0;
      analogWrite(DISP_BRIGHTNESS_PIN,
	      eeprom_read_byte((unsigned char*) EEPROM_DISP_BRIGHTNESS));
    }

    if (state == KP_OCTOTHORP) {
      menuShow(&mainMenu);
    } else {
    
      /* Call the menu's key handler */
      Menu* (*keyfn)(byte) = (Menu* (*)(byte))
................................................................................
	menuShow(nextMenu);
      }
    }

    /* Wind the clock */
    menuLastKeyMillis = now;
  }

}
 
/*
 *-----------------------------------------------------------------------------
 *
 * menuSelHandler --
 *
................................................................................
/*
 *-----------------------------------------------------------------------------
 *
 * mainMenuHandler --
 *
 *	Handle keypresses at the main menu
 *

 * This procedure does quick stop programming for numeric keys, or starts
 * programming if * is pressed. (# requests a manual card read, which can
 * be done at any time that we're neither in standby nor sending a card image.)
 *
 *-----------------------------------------------------------------------------
 */
Menu*
mainMenuHandler(byte key)
{


  if (key <= 9) {

    /* 
     * Quick programming of stops - pull a preset from EEPROM and send
     * it to the organ.
     */
................................................................................
    }
  } else if (key == KP_ASTERISK) {
    sendToOrgan();
  }
  return &mainMenu;
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * sendToOrgan --
 *
 *	Send the currently selected stop to the organ.
 *
 * Composes a command string consisting of the letter S followed by
 * 32 hexadecimal digits, and a newline, and sends it to the LED controller
 * (This causes the LED controller to flash the LEDs in the given pattern,
 * simulating the insertion and removal of a punch card.)
 *
 *-----------------------------------------------------------------------------
 */

void
sendToOrgan(void) {
  int i;
  ps2SendByte('S');
  for (i = 0; i < 16; ++i) {
    ps2SendByte(pgm_read_byte(HexTable + (selectedStop[i] >> 4)));
    ps2SendByte(pgm_read_byte(HexTable + (selectedStop[i] & 0xf)));
  }
  ps2SendByte('\n');
  menuShow(menuCurrent);
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * setup --
 *
 *	Initialize the terminal
 *
 * This function initializes the I/O for the keypad, the display, and
 * the PS/2 keyboard port.  It sets the current time, and initializes the
 * menu system. It also tells the LED controller to wake up, in case it was
 * in standby.
 *
 *-----------------------------------------------------------------------------
 */

void
setup() {

  kpInit();			/* Initialize the keypad */
  dispInit();			/* Initialize the display */
  ps2Init();			/* Initialize the communication port */

  now = millis();		/* Set the clock */

  menuLastKeyMillis = now;	/* Set the standby timer for the menu system */
  menuStandby = 0;
  menuShow(&mainMenu);		/* Show the main menu */



  ps2SendByte('W');		/* Wake up the LED controller */

  ps2SendByte('\n');
}
 

/*
 *-----------------------------------------------------------------------------
 *
 * loop --
 *
 *	Main scan loop for the system
 *
 * This function sets 'now' to the current time. It asks the menu system
 * to poll keyboard and update display, and services the communication
 * port to send any pending text.
 *
 *-----------------------------------------------------------------------------
 */

void
loop() {

  now = millis();		/* Wind the clock */

  menuPoll();			/* Service the keyboard and display */
  ps2Poll();			/* Service the communication port */

}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 2
 * End:
 */