Hi all,
I need to understand how the loop() function gets invoked under the covers for Teensy 3.6. I'm working with interrupts and I don't know if my interrupt enabling/disabling will screw up the loop() function, or if the loop() function is the main thread of the processor.
What's the best way to see how your code is actually being generated under the covers?
I need to understand how the loop() function gets invoked under the covers for Teensy 3.6. I'm working with interrupts and I don't know if my interrupt enabling/disabling will screw up the loop() function, or if the loop() function is the main thread of the processor.
What's the best way to see how your code is actually being generated under the covers?
Code:
#include <stdarg.h>
#define L1_RED() digitalWriteFast(21,HIGH);digitalWriteFast(22,LOW); digitalWriteFast(23,LOW);
#define L1_GREEN() digitalWriteFast(21,LOW); digitalWriteFast(22,LOW); digitalWriteFast(23,HIGH);
#define L1_BLUE() digitalWriteFast(21,LOW); digitalWriteFast(22,HIGH);digitalWriteFast(23,LOW);
#define L1_YELLOW() digitalWriteFast(21,HIGH);digitalWriteFast(22,LOW); digitalWriteFast(23,HIGH);
#define L1_CYAN() digitalWriteFast(21,LOW); digitalWriteFast(22,HIGH);digitalWriteFast(23,HIGH);
#define L1_VIOLET() digitalWriteFast(21,HIGH);digitalWriteFast(22,HIGH);digitalWriteFast(23,LOW);
#define L1_WHITE() digitalWriteFast(21,HIGH);digitalWriteFast(22,HIGH);digitalWriteFast(23,HIGH);
#define L1_BLACK() digitalWriteFast(21,LOW); digitalWriteFast(22,LOW); digitalWriteFast(23,LOW);
#define L2_RED() digitalWriteFast(18,HIGH);digitalWriteFast(19,LOW); digitalWriteFast(20,LOW);
#define L2_BLUE() digitalWriteFast(18,LOW); digitalWriteFast(19,HIGH);digitalWriteFast(20,LOW);
#define L2_GREEN() digitalWriteFast(18,LOW); digitalWriteFast(19,LOW); digitalWriteFast(20,HIGH);
#define L2_CYAN() digitalWriteFast(18,LOW); digitalWriteFast(19,HIGH);digitalWriteFast(20,HIGH);
#define L2_VIOLET() digitalWriteFast(18,HIGH);digitalWriteFast(19,HIGH);digitalWriteFast(20,LOW);
#define L2_YELLOW() digitalWriteFast(18,HIGH);digitalWriteFast(19,LOW); digitalWriteFast(20,HIGH);
#define L2_WHITE() digitalWriteFast(18,HIGH);digitalWriteFast(19,HIGH);digitalWriteFast(20,HIGH);
#define L2_BLACK() digitalWriteFast(18,LOW); digitalWriteFast(19,LOW); digitalWriteFast(20,LOW);
#define A1 37
#define A0 36
#define INTERUPT_TO_TRS80 35
#define _37ECWR 34
#define _37E8WR 33
#define FF_PRE 29
#define _37E4WR 28
#define _37E0WR 27
#define _37ECRD 26
#define FF_CLR 25
#define _37E8RD 12
#define _37E4RD 11
#define _37E0RD 10
#define D7 9
#define D6 8
#define D5 7
#define D4 6
#define D3 5
#define D2 4
#define D1 3
#define D0 2
#define NOTHING 0
volatile byte activeInterrupt = NOTHING;
/* printf() to serial output */
void p(char *fmt, ... ){
char buf[80];
va_list args;
va_start (args, fmt );
vsnprintf(buf, 128, fmt, args);
va_end (args);
Serial.print(buf);
}
/* direct data bus pins outward */
void dataOutMode() {
pinMode(D7,OUTPUT);
pinMode(D6,OUTPUT);
pinMode(D5,OUTPUT);
pinMode(D4,OUTPUT);
pinMode(D3,OUTPUT);
pinMode(D2,OUTPUT);
pinMode(D1,OUTPUT);
pinMode(D0,OUTPUT);
}
/* direct data bus pins inward */
void dataInMode() {
pinMode(D7,INPUT);
pinMode(D6,INPUT);
pinMode(D5,INPUT);
pinMode(D4,INPUT);
pinMode(D3,INPUT);
pinMode(D2,INPUT);
pinMode(D1,INPUT);
pinMode(D0,INPUT);
}
/* set up pin directionality */
void pinSetup() {
pinMode(18,OUTPUT); // L2 LEDs (leg pins may be rearranged depending on what RGB LED used -- just change the macro names around)
pinMode(19,OUTPUT); // L2 LEDs
pinMode(20,OUTPUT); // L2 LEDs
pinMode(21,OUTPUT); // L1 LEDs
pinMode(22,OUTPUT); // L1 LEDs
pinMode(23,OUTPUT); // L1 LEDs
pinMode(39,OUTPUT); // nothing, unused pin
pinMode(38,OUTPUT); // nothing, unused pin
pinMode(A1, INPUT); // A1 from TRS-80
pinMode(A0, INPUT); // A0 from TRS-80
pinMode(INTERUPT_TO_TRS80, OUTPUT); // pin to trigger interrupts on the TRS-80
pinMode(_37ECWR, INPUT); // pin to detect when write to address 37EC has been triggered (low)
pinMode(_37E8WR, INPUT); // pin to detect when write to address 37E8 has been triggered (low)
pinMode(30,OUTPUT); // nothing, unused pin
pinMode(FF_PRE,OUTPUT); // flip flop PRE
pinMode(_37E4WR,INPUT); // pin to detect when write to address 37E4 has been triggered (low)
pinMode(_37E0WR,INPUT); // pin to detect when write to address 37E0 has been triggered (low)
pinMode(_37ECRD,INPUT); // pin to detect when read from address 37E0 has been triggered (low)
pinMode(FF_CLR,OUTPUT); // flip flop CLR
pinMode(_37E8RD,INPUT); // pin to detect when read from address 37E8 has been triggered (low)
pinMode(_37E4RD,INPUT); // pin to detect when read from address 37E4 has been triggered (low)
pinMode(_37E0RD,INPUT); // pin to detect when read from address 37E0 has been triggered (low)
dataInMode();
}
/* jigger the flip flop that's tied to the WAIT* line on the TRS-80 to make sure it's in a known state */
void initFlipFlop() {
digitalWrite(FF_PRE,LOW);
digitalWrite(FF_CLR,LOW);
digitalWrite(FF_PRE,HIGH);
digitalWrite(FF_CLR,LOW);
digitalWrite(FF_PRE,LOW);
digitalWrite(FF_CLR,HIGH);
digitalWrite(FF_PRE,HIGH);
digitalWrite(FF_CLR,LOW);
digitalWrite(FF_PRE,HIGH);
digitalWrite(FF_CLR,HIGH);
}
/* initialize output pins */
void initialPinState() {
digitalWriteFast(INTERUPT_TO_TRS80, HIGH); // turn off TRS-80 interrupt line (it's active low)
initFlipFlop(); // jigger flip flop into a known state (loaded, ready for trigger)
}
/* reset the latch that's tied to TRS-80 WAIT* line */
inline void resetWaitLatch() {
digitalWriteFast(FF_PRE,HIGH);
digitalWriteFast(FF_CLR,HIGH);
}
#define DISABLE_INTR_AND_WAIT() cli(); while(activeInterrupt != NOTHING);
void _37E0WRInterrupt() {
DISABLE_INTR_AND_WAIT()
activeInterrupt = _37E0WR;
}
void _37E8WRInterrupt() {
DISABLE_INTR_AND_WAIT()
activeInterrupt = _37E8WR;
}
void _37E4WRInterrupt() {
DISABLE_INTR_AND_WAIT()
activeInterrupt = _37E4WR;
}
void _37ECWRInterrupt() {
DISABLE_INTR_AND_WAIT()
activeInterrupt = _37ECWR;
}
void _37ECRDInterrupt() {
DISABLE_INTR_AND_WAIT()
activeInterrupt = _37ECRD;
}
void _37E8RDInterrupt() {
DISABLE_INTR_AND_WAIT()
activeInterrupt = _37E8RD;
}
void _37E4RDInterrupt() {
DISABLE_INTR_AND_WAIT()
activeInterrupt = _37E4RD;
}
void _37E0RDInterrupt() {
DISABLE_INTR_AND_WAIT()
activeInterrupt = _37E0RD;
}
/* retrieve content of data bus */
byte getDataBus() {
byte x = 0;
if(digitalReadFast(D7) == HIGH) x+=128;
if(digitalReadFast(D6) == HIGH) x+=64;
if(digitalReadFast(D5) == HIGH) x+=32;
if(digitalReadFast(D4) == HIGH) x+=16;
if(digitalReadFast(D3) == HIGH) x+=8;
if(digitalReadFast(D2) == HIGH) x+=4;
if(digitalReadFast(D1) == HIGH) x+=2;
if(digitalReadFast(D0) == HIGH) x+=1;
return x;
}
/* set the value of the data bus */
void setDataBus(byte b) {
byte x = b;
if(x >= 128) {digitalWriteFast(D7,HIGH); x-=128;} else {digitalWriteFast(D7,LOW);}
if(x >= 64) {digitalWriteFast(D6,HIGH); x-=64; } else {digitalWriteFast(D6,LOW);}
if(x >= 32) {digitalWriteFast(D5,HIGH); x-=32; } else {digitalWriteFast(D5,LOW);}
if(x >= 16) {digitalWriteFast(D4,HIGH); x-=16; } else {digitalWriteFast(D4,LOW);}
if(x >= 8) {digitalWriteFast(D3,HIGH); x-=8; } else {digitalWriteFast(D3,LOW);}
if(x >= 4) {digitalWriteFast(D2,HIGH); x-=4; } else {digitalWriteFast(D2,LOW);}
if(x >= 2) {digitalWriteFast(D1,HIGH); x-=2; } else {digitalWriteFast(D1,LOW);}
if(x >= 1) {digitalWriteFast(D0,HIGH); } else {digitalWriteFast(D0,LOW);}
}
/* wire up the interrupts */
void configureInterrupts() {
attachInterrupt(digitalPinToInterrupt(_37ECWR), _37ECWRInterrupt, LOW);
attachInterrupt(digitalPinToInterrupt(_37E8WR), _37E8WRInterrupt, LOW);
attachInterrupt(digitalPinToInterrupt(_37E4WR), _37E4WRInterrupt, LOW);
attachInterrupt(digitalPinToInterrupt(_37E0WR), _37E0WRInterrupt, LOW);
attachInterrupt(digitalPinToInterrupt(_37ECRD), _37ECRDInterrupt, LOW);
attachInterrupt(digitalPinToInterrupt(_37E8RD), _37E8RDInterrupt, LOW);
attachInterrupt(digitalPinToInterrupt(_37E4RD), _37E4RDInterrupt, LOW);
attachInterrupt(digitalPinToInterrupt(_37E0RD), _37E0RDInterrupt, LOW);
}
/* initialize everything */
void setup() {
int i = 0;
cli();
Serial.begin(2000000); // high speed serial over USB
pinSetup(); // set pin modes
initialPinState(); // put pins in initial configuration
L1_RED();
L2_RED();
while(!Serial && i < 10) {
i++;
delay(100);
L2_YELLOW();
delay(100);
L2_RED();
}
L2_GREEN();
configureInterrupts(); // tie interrupt lines to code blocks
L1_GREEN();
sei();
}
/* Main Loop */
/* --------- */
/* When activeInterrupt changes, split it into a "read" or "write" request */
/* For read requests, set data bus direction to outward (from the Teensy */
/* to the TRS-80). For write requests, set the data bus direction to */
/* inward (from the TRS-80 to the Teensy). */
/* */
/* Then switch into each address's intended function */
void loop() {
if(activeInterrupt != NOTHING) {
if(activeInterrupt == _37ECWR || activeInterrupt == _37E8WR || activeInterrupt == _37E4WR || activeInterrupt == _37E0WR) {
dataInMode();
L1_CYAN();
byte b = getDataBus();
p("write - ");
if(activeInterrupt == _37ECWR) {
L2_RED();
p("Disk command register - 0x37EC - %2X\n",b);
}
else
if(activeInterrupt == _37E8WR) {
L2_BLUE();
p("Line printer data port - 0x37E8 - %2X\n",b);
}
else
if(activeInterrupt == _37E4WR) {
L2_YELLOW();
p("Cassette drive latch - 0x37E4 - %2X\n",b);
}
else {
L2_VIOLET();
p("Disk drive select latch - 0x37E0 - %2X\n",b);
}
}
else {
dataOutMode();
L1_VIOLET();
p("read - ");
if(activeInterrupt == _37ECRD) {
L2_RED();
p("Disk status register - 0x37EC\n");
setDataBus(0);
}
else
if(activeInterrupt == _37E8RD) {
L2_BLUE();
p("Line printer status port- 0x37E8\n");
setDataBus(0);
}
else
if(activeInterrupt == _37E4RD) {
L2_YELLOW();
p("Cassette drive latch - 0x37E4\n");
setDataBus(0);
}
else {
L2_VIOLET();
p("Disk drive select latch - 0x37E0\n");
setDataBus(0);
}
}
L1_GREEN();
L2_GREEN();
activeInterrupt = NOTHING;
resetWaitLatch();
sei();
}
}
Last edited: