2013-03-14 16:48:10 +00:00
|
|
|
/* requires keypad library by Mark Stanley, Alexander Brevig from:
|
2017-04-10 14:09:20 +00:00
|
|
|
http://www.arduino.cc/playground/Code/Keypad
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
Uses the PJRC Teensy++ 2.0 and Teensyduino libraries, specifically USB HID and Keyboard():
|
|
|
|
http://www.pjrc.com/teensy/teensyduino.html
|
2013-03-14 16:48:10 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <Keypad.h>
|
|
|
|
|
2014-08-01 02:39:52 +00:00
|
|
|
// added breakout pins for DISK READ LED, KEYBOARD SWITCH, and 40/80 COLUMN SWITCH (rev.4 board)
|
|
|
|
int LEDPin = 8;
|
|
|
|
int DvorakPin = 9;
|
|
|
|
int ColumnsPin = 10;
|
|
|
|
|
|
|
|
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
/*
|
|
|
|
Declares the matrix rows/cols of the Apple IIc keyboard.
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
// Prevent compiler warning about casts from unsigned ints to chars
|
|
|
|
#define C(x) ((char) (x))
|
|
|
|
|
2013-03-14 16:48:10 +00:00
|
|
|
const byte ROWS = 8; // rows
|
|
|
|
const byte COLS = 10; // columns
|
|
|
|
char keys[ROWS][COLS] = {
|
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
{ C(KEY_ESC), C(KEY_1), C(KEY_2), C(KEY_3), C(KEY_4), C(KEY_6), C(KEY_5), C(KEY_7), C(KEY_8), C(KEY_9) },
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
{ C(KEY_TAB), C(KEY_Q), C(KEY_W), C(KEY_E), C(KEY_R), C(KEY_Y), C(KEY_T), C(KEY_U), C(KEY_I), C(KEY_O)},
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
{ C(KEY_A), C(KEY_D), C(KEY_S), C(KEY_H), C(KEY_F), C(KEY_G), C(KEY_J), C(KEY_K), C(KEY_SEMICOLON), C(KEY_L)},
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
{ C(KEY_Z), C(KEY_X), C(KEY_C), C(KEY_V), C(KEY_B), C(KEY_N), C(KEY_M), C(KEY_COMMA), C(KEY_PERIOD), C(KEY_SLASH)},
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
{ 0, 0, 0, 0, 0, 0, C(KEY_BACKSLASH), C(KEY_EQUAL), C(KEY_0), C(KEY_MINUS)},
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
{ 0, 0, 0, 0, 0, 0, C(KEY_TILDE), C(KEY_P), C(KEY_LEFT_BRACE), C(KEY_RIGHT_BRACE)},
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
{ 0, 0, 0 , 0, 0, 0, C(KEY_ENTER), C(KEY_UP), C(KEY_SPACE), C(KEY_QUOTE)},
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
{ 0, 0, 0, 0, 0, 0, C(KEY_BACKSPACE), C(KEY_DOWN), C(KEY_LEFT), C(KEY_RIGHT)},
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
char Fkeys[2][10] = {
|
|
|
|
{C(KEY_1), C(KEY_2), C(KEY_3), C(KEY_4), C(KEY_5), C(KEY_6), C(KEY_7), C(KEY_8), C(KEY_9), C(KEY_0)},
|
|
|
|
{C(KEY_F1), C(KEY_F2), C(KEY_F3), C(KEY_F4), C(KEY_F5), C(KEY_F6), C(KEY_F7), C(KEY_F8), C(KEY_F9), C(KEY_F10)}
|
|
|
|
};
|
|
|
|
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
2017-04-10 14:09:20 +00:00
|
|
|
Keyboard matrix
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
X0 1 2 3 4 5 6 7 8 9
|
2017-04-10 14:09:20 +00:00
|
|
|
Y0 ESC 1 2 3 4 6 5 7 8 9
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
1 TAB Q W E R Y T U I O
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
2 A D S H F G J K ; L
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
3 Z X C V B N M < > ?
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
4 \ + 0 -
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
5 ~ P [ ]
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
6 RET UP SPC "
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
7 DEL DN LT RT
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
Matrix
|
2013-03-14 16:48:10 +00:00
|
|
|
J9 Teensy
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
X0 31 26
|
|
|
|
1 24 4
|
|
|
|
2 22 5
|
|
|
|
3 8 14
|
|
|
|
4 14 17
|
|
|
|
5 6 13
|
|
|
|
6 10 15
|
|
|
|
7 1 3
|
|
|
|
8 4 12
|
|
|
|
9 2 11
|
|
|
|
|
|
|
|
Y0 12 16
|
|
|
|
1 33 25
|
|
|
|
2 18 7
|
|
|
|
3 20 38
|
|
|
|
4 3 2
|
|
|
|
5 5 1
|
|
|
|
6 7 0
|
|
|
|
7 9 27
|
|
|
|
|
|
|
|
NC 13
|
2013-03-14 16:48:10 +00:00
|
|
|
17
|
|
|
|
30
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
GND 21
|
|
|
|
|
|
|
|
SFT 34 24
|
|
|
|
CTL 32 23
|
|
|
|
CMD 16 8
|
|
|
|
CMD 26 20
|
|
|
|
CAPS 28 21
|
|
|
|
|
|
|
|
|
|
|
|
J9 pinout
|
|
|
|
1 X7
|
|
|
|
2 X9
|
|
|
|
3 Y4
|
|
|
|
4 X8
|
|
|
|
5 Y5
|
|
|
|
6 X5
|
|
|
|
7 Y6
|
|
|
|
8 X3
|
|
|
|
9 Y7
|
|
|
|
10 X6
|
|
|
|
11 DISK LED (5v)
|
|
|
|
12 Y0
|
|
|
|
13 NC
|
|
|
|
14 X4
|
|
|
|
15 KEYBOARD SW
|
|
|
|
16 CLOSED APPLE
|
|
|
|
17 NC
|
|
|
|
18 Y2
|
|
|
|
19 40/80 COL SWITCH
|
|
|
|
20 Y3
|
|
|
|
21 GROUND ???
|
|
|
|
22 X2
|
|
|
|
23 GROUND ???
|
|
|
|
24 X1
|
|
|
|
25 POWER LED (5v)
|
|
|
|
26 OPEN APPLE
|
|
|
|
27 LED GROUND ???
|
|
|
|
28 CAPS LOCK
|
|
|
|
29 RESET
|
|
|
|
30 NC
|
|
|
|
31 X0
|
|
|
|
32 CONTROL
|
|
|
|
33 Y1
|
|
|
|
34 SHIFT
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
byte rowPins[ROWS] = { // Y0 - Y9
|
2017-04-10 14:09:20 +00:00
|
|
|
16, 25, 7, 38, 2, 1, 0, 27
|
|
|
|
}; //connect to the row pinouts of the keypad
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
byte colPins[COLS] = { // X0 - X7
|
2017-04-10 14:09:20 +00:00
|
|
|
26, 4, 5, 14, 17, 13, 15, 3, 12, 11
|
|
|
|
}; //connect to the column pinouts of the keypad
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
Keypad KPD = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
|
|
|
|
|
|
|
|
|
|
|
|
const int SHIFTPin = 24; // the pin that the shift key is attached to
|
|
|
|
const int CTRLPin = 23; // the pin that the control key is attached to
|
|
|
|
const int APPLEPin1 = 43; // the pin that the open-apple key is attached to
|
|
|
|
const int APPLEPin2 = 44; // the pin that the closed-apple key is attached to
|
2013-04-22 19:26:36 +00:00
|
|
|
|
|
|
|
const int CAPSPin = 21;
|
2013-03-14 16:48:10 +00:00
|
|
|
// these pins are special in that they are dis/connected to ground, instead of to a row/col
|
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
/***
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
open/closed apple are grounded through resistors on the //c. need to detect voltage drop as analogread, not digital.
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
must be on analog pin.
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
***/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char modifierKeys[4];
|
|
|
|
|
|
|
|
|
2013-05-01 20:01:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
#define KEY_CAPS_UNLOCK 0
|
2013-05-01 20:01:08 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
boolean resetCapsLock = false; // Allows one caps unlock signal.
|
|
|
|
unsigned long dTime = 0;
|
|
|
|
boolean CAPSLock = false; // Initialize this to a reasonable value.
|
2013-05-01 20:01:08 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
boolean FKEYS = false; // used to set numbers to F-Key equivalent. currently tied to caps lock
|
2013-05-01 20:01:08 +00:00
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
void setup() {
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
pinMode(SHIFTPin, INPUT);
|
|
|
|
pinMode(CTRLPin, INPUT);
|
|
|
|
pinMode(APPLEPin1, INPUT);
|
|
|
|
pinMode(APPLEPin2, INPUT);
|
|
|
|
|
2013-04-22 19:26:36 +00:00
|
|
|
digitalWrite(APPLEPin1, HIGH);
|
|
|
|
digitalWrite(APPLEPin2, HIGH);
|
2017-04-10 14:09:20 +00:00
|
|
|
|
2013-04-22 19:26:36 +00:00
|
|
|
digitalWrite(SHIFTPin, HIGH);
|
|
|
|
digitalWrite(CTRLPin, HIGH);
|
2017-04-10 14:09:20 +00:00
|
|
|
|
2013-04-22 19:26:36 +00:00
|
|
|
pinMode(CAPSPin, INPUT);
|
|
|
|
digitalWrite(CAPSPin, HIGH);
|
2017-04-10 14:09:20 +00:00
|
|
|
|
2014-08-01 02:39:52 +00:00
|
|
|
// Turn on the DISK READ LED (rev4 board)
|
2017-04-10 14:09:20 +00:00
|
|
|
// digitalWrite(LEDPin, HIGH);
|
|
|
|
// This gives time for the keyboard to hook up to the PC.
|
|
|
|
// Otherwise the caps lock state may be incorrect.
|
|
|
|
delay(1000);
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void loop()
|
|
|
|
{
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
//probably should be on an interrupt, to catch high->low transition
|
2013-04-22 19:26:36 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
// Only do something if the pin is different from previous state.
|
|
|
|
boolean newCaps = digitalRead(CAPSPin) ? false : true;
|
2013-05-01 20:01:08 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
if ( (CAPSLock != newCaps) && !resetCapsLock)
|
|
|
|
{
|
|
|
|
CAPSLock = newCaps; // Remember new CAPSLock.
|
|
|
|
Keyboard.set_key6((uint8_t) KEY_CAPS_LOCK); // Send KEY_CAPS_LOCK.
|
|
|
|
dTime = millis(); // Reset delay timer.
|
|
|
|
resetCapsLock = true;
|
2013-10-24 15:35:45 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
// Serial.print("Caps = ");
|
|
|
|
// Serial.println(CAPSLock);
|
2013-10-24 15:35:45 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
// Turn on the LED for caps lock.
|
|
|
|
// digitalWrite(LED, CAPSLock ? HIGH : LOW);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( resetCapsLock && (millis() - dTime) > 10)
|
|
|
|
{
|
|
|
|
Keyboard.set_key6(KEY_CAPS_UNLOCK);
|
|
|
|
resetCapsLock = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If caps lock is set, then turn number keys into function keys.
|
|
|
|
FKEYS = CAPSLock;
|
|
|
|
|
|
|
|
/*char CAPSState = digitalRead(CAPSPin);
|
|
|
|
if (CAPSState == LOW) {
|
|
|
|
Keyboard.set_key6(KEY_CAPS_LOCK);
|
|
|
|
} else {
|
|
|
|
Keyboard.set_key6(0);
|
|
|
|
}
|
2013-04-22 19:26:36 +00:00
|
|
|
|
2013-05-01 20:01:08 +00:00
|
|
|
*/
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
char SHIFTState = digitalRead(SHIFTPin);
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
if (SHIFTState == LOW) {
|
|
|
|
modifierKeys[0] = MODIFIERKEY_SHIFT;
|
|
|
|
digitalWrite(SHIFTPin, HIGH);
|
|
|
|
} else {
|
|
|
|
digitalWrite(SHIFTPin, HIGH);
|
|
|
|
modifierKeys[0] = 0;
|
|
|
|
}
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
char CTRLState = digitalRead(CTRLPin);
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
if (CTRLState == LOW) {
|
|
|
|
modifierKeys[1] = MODIFIERKEY_CTRL;
|
|
|
|
digitalWrite(CTRLPin, HIGH);
|
|
|
|
} else {
|
|
|
|
modifierKeys[1] = 0;
|
|
|
|
digitalWrite(CTRLPin, HIGH);
|
|
|
|
}
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
char OAPPLEState = analogRead(APPLEPin2);
|
|
|
|
char CAPPLEState = analogRead(APPLEPin1);
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
// *** NOW USING CLOSED APPLE AS ALT/OPTION
|
|
|
|
if (OAPPLEState < 20) {
|
|
|
|
modifierKeys[2] = MODIFIERKEY_GUI;
|
|
|
|
digitalWrite(APPLEPin1, HIGH);
|
|
|
|
} else {
|
|
|
|
modifierKeys[2] = 0;
|
|
|
|
digitalWrite(APPLEPin1, HIGH);
|
|
|
|
}
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (CAPPLEState < 20) {
|
|
|
|
modifierKeys[3] = MODIFIERKEY_ALT;
|
|
|
|
digitalWrite(APPLEPin2, HIGH);
|
|
|
|
} else {
|
|
|
|
modifierKeys[3] = 0;
|
|
|
|
digitalWrite(APPLEPin2, HIGH);
|
|
|
|
}
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
// to use the TILDE key as ALT/OPTION
|
|
|
|
/* modifierKeys[3] = 0;
|
|
|
|
if( KPD.isPressed(KEY_TILDE) ) {
|
|
|
|
modifierKeys[3] = MODIFIERKEY_ALT;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
// *** NOW USING CLOSED APPLE AS ALT/OPTION
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
Keyboard.set_modifier( modifierKeys[0] | modifierKeys[1] | modifierKeys[2] | modifierKeys[3] );
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
KPD.getKeys(); // Scan for all pressed keys. 6 Max, + 4 modifiers. Should be plenty, but can be extended to 10+
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
// Set keyboard keys to default values.
|
|
|
|
Keyboard.set_key1(0);
|
|
|
|
Keyboard.set_key2(0);
|
|
|
|
Keyboard.set_key3(0);
|
|
|
|
Keyboard.set_key4(0);
|
|
|
|
Keyboard.set_key5(0);
|
|
|
|
//Keyboard.set_key6(0);
|
|
|
|
|
|
|
|
/* based on suggestion from Craig Brooks <s.craig.brooks@gmail.com>
|
|
|
|
uses CAPS LOCK to turn number keys into F-Key equivalent.
|
|
|
|
*/
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
// Update keyboard keys to active values.
|
|
|
|
if ( KPD.key[0].kchar && ( KPD.key[0].kstate == PRESSED || KPD.key[0].kstate == HOLD )) {
|
2013-10-24 15:35:45 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
//Serial.println(FKEYS);
|
|
|
|
|
|
|
|
|
|
|
|
if (FKEYS) {
|
|
|
|
// number keys 1 through 0 for f1 - f10
|
|
|
|
if ((KPD.key[0].kchar >= 0x1E) && (KPD.key[0].kchar <= 0x27)) {
|
|
|
|
KPD.key[0].kchar += 0x1C;
|
|
|
|
|
|
|
|
// Serial.println( KPD.key[0].kchar, HEX );
|
|
|
|
|
|
|
|
// - and = for f11 and f12
|
|
|
|
} else if ( KPD.key[0].kchar == 0x2D || KPD.key[0].kchar == 0x2E ) {
|
|
|
|
KPD.key[0].kchar += 0x17;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2013-10-24 15:35:45 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
Keyboard.set_key1( KPD.key[0].kchar );
|
2013-10-24 15:35:45 +00:00
|
|
|
|
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
}
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
if ( KPD.key[1].kchar && ( KPD.key[1].kstate == PRESSED || KPD.key[1].kstate == HOLD ))
|
|
|
|
Keyboard.set_key2( KPD.key[1].kchar );
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
if ( KPD.key[2].kchar && ( KPD.key[2].kstate == PRESSED || KPD.key[2].kstate == HOLD ))
|
|
|
|
Keyboard.set_key3( KPD.key[2].kchar );
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
if ( KPD.key[3].kchar && ( KPD.key[3].kstate == PRESSED || KPD.key[3].kstate == HOLD ))
|
|
|
|
Keyboard.set_key4( KPD.key[3].kchar );
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
if ( KPD.key[4].kchar && ( KPD.key[4].kstate == PRESSED || KPD.key[4].kstate == HOLD ))
|
|
|
|
Keyboard.set_key5( KPD.key[4].kchar );
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
//if( KPD.key[5].kchar && ( KPD.key[5].kstate==PRESSED || KPD.key[5].kstate==HOLD ))
|
|
|
|
//Keyboard.set_key6( KPD.key[5].kchar );
|
2013-03-14 16:48:10 +00:00
|
|
|
|
2017-04-10 14:09:20 +00:00
|
|
|
Keyboard.send_now();
|
|
|
|
Keyboard.set_modifier(0);
|
2013-03-14 16:48:10 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|