macsonny Posted October 21, 2023 Author Share Posted October 21, 2023 13 hours ago, Chri O. said: Only manage to fix my drive and I can confirm that the display does not work correctly with Tandon Drive. Will look into this later today. Thanks. Looking forward to what you find out. Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 22, 2023 Share Posted October 22, 2023 This thing is giving me headache😁 Tandon Drive quick preview. 20231022_143440.mp4 Now I need to grease the bearing on top of the drive... 1 Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 22, 2023 Share Posted October 22, 2023 Ok this need more testing but anyways... Tandon Drive ARDUINO UNO only ATmega328 AVR Pin Change Interrupt in use 🙂 /********************************************************************* MIT License Copyright (c) [2023] [Chris O.] Atari 1050 - Track Display, ver 03. For Tandon Drive. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *********************************************************************/ // https://github.com/wonho-maker/Adafruit_SH1106 /********************************************************************* Change the adafruit SSD1306 to SH1106 SH1106 driver don't provide several functions such as scroll commands. *********************************************************************/ // Teensy SH1106 driver fix https://forum.pjrc.com/threads/68174-OLED-problems #pragma message("Tandon Drive ARDUINO UNO only ATmega328 AVR Pin Change Interrupt in use") #define DEBUG 0 // Serial(115200) SET TO 0 REMOVE DEBUG, 1 DEBUG ON const byte VER = 03; // NOTE: It is a good idea to connect OUTPUT-INPUT pins to other devices with // 470ohm or 1k resistors for Short circuit current-limiting. // ARDUINO UNO const byte interruptPin_NS01 = 4; // NS01 @ U2 ic pin 2, NOT USED FOR interrupt. const byte interruptPin_NS02 = 2; // NS02 @ U2 ic pin 7 Hardware interrupt. const byte interruptPin_NS03 = 5; // NS03 @ U3 ic pin 2 For PCINT interrupt. PCINT21 -- ATmega328 const byte interruptPin_NS04 = 3; // NS04 @ U3 ic pin 7 Hardware interrupt. const byte N_TRACK00_Pin = 6; // Look for Q5 and C47,C50 on 1050 motherboard // connect closer to the C47,C50 side @ R#59 Track 00 sensor. // // MCU GND to 1050 TP15 GND (test point 15). // Optional +5v available @ 1050 TP13. // ATmega328 AVR HACK, PCINT pin change interrupt bool D4_state = false; bool D5_state = false; volatile byte Tcount = 0; volatile unsigned long timeNS01 = 0; // PCINT pin change interrupt TIME volatile unsigned long timeNS02 = 0; volatile unsigned long timeNS03 = 0; // PCINT pin change interrupt TIME volatile unsigned long timeNS04 = 0; bool received = false; // byte NewTcount = Tcount; byte OldTcount = Tcount; #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> //TODO #include <Adafruit_SSD1306> // 0.91 Inch I2C OLED Display #include <Adafruit_SH1106.h> // OLED 1.30" @ I2C addr. 0x3C #define OLED_RESET -1 // -1, NO RESET Adafruit_SH1106 display(OLED_RESET); #define LOGO16_GLCD_HEIGHT 16 #define LOGO16_GLCD_WIDTH 16 static const unsigned char PROGMEM logo16_glcd_bmp[] = { B00000000, B11000000, B00000001, B11000000, B00000001, B11000000, B00000011, B11100000, B11110011, B11100000, B11111110, B11111000, B01111110, B11111111, B00110011, B10011111, B00011111, B11111100, B00001101, B01110000, B00011011, B10100000, B00111111, B11100000, B00111111, B11110000, B01111100, B11110000, B01110000, B01110000, B00000000, B00110000 }; void setup() { // put your setup code here, to run once: Serial.begin(115200); while (!Serial && millis() < 4000 ); Serial.print("Basic ARDUINO UNO 1050(For Tandon Drive) Test: v.0"); Serial.println(VER); // SH1106 driver display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64), SH1106 addr 0x3C. display.SH1106_command(0X81); // SETCONTRAST display.SH1106_command(255); // VALUE 0 TO 255 // Show image buffer on the display hardware. // Since the buffer is intialized with an Adafruit splashscreen // internally, this will display the splashscreen. display.display(); delay(1000); // Clear the buffer. display.clearDisplay(); // Show the display buffer on the hardware. // NOTE: You _must_ call display after making any drawing commands // to make them visible on the display hardware! display.display(); display.setTextSize(2); // display.setTextColor(WHITE); display.setTextColor(BLACK, WHITE); // 'inverted' text display.setCursor(0, 5); display.println("Atari 1050"); // display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(10, 30); display.println("Track Display Test"); // display.setCursor(10, 55); display.print("V.0"); display.println(VER); display.display(); // display setup for loop() display.clearDisplay(); display.setCursor(5, 5); display.setTextSize(9); delay(1000); if (NewTcount < 10) { display.print("0"); } display.print(NewTcount); display.display(); display.SH1106_command(0X81); // SETCONTRAST display.SH1106_command(50); // CONTRAST VALUE 0 TO 255 pinMode(LED_BUILTIN, OUTPUT); // NOTE: on UNO pin 13 pinMode(N_TRACK00_Pin, INPUT_PULLUP); pinMode(interruptPin_NS01, INPUT_PULLUP); pinMode(interruptPin_NS02, INPUT_PULLUP); // edge-triggered interrupt on rising edge (low to high). attachInterrupt(digitalPinToInterrupt(interruptPin_NS02), IRQ_NS02, FALLING); //RISING, CHANGE, FALLING pinMode(interruptPin_NS03, INPUT_PULLUP); pinMode(interruptPin_NS04, INPUT_PULLUP); // edge-triggered interrupt on rising edge (low to high). attachInterrupt(digitalPinToInterrupt(interruptPin_NS04), IRQ_NS04, RISING); //RISING, CHANGE, FALLING // For ATmega328 AVR ONLY, PCINT Pin Change Interrupt PCICR |= B00000100; //Bit2 = 1 -> "PCIE2" enabeled (PCINT16 to PCINT23) PCMSK2 |= B00100000; //Bit5 = 1 -> "PCINT21" enabeled } void loop() { // put your main code here, to run repeatedly: noInterrupts(); NewTcount = Tcount; interrupts(); if (digitalRead(N_TRACK00_Pin) == HIGH) { // if Track 0 sensor @5volts then set TRACK count to 0 NewTcount = 0; noInterrupts(); Tcount = 0; interrupts(); received = false; } if (OldTcount != NewTcount) { // for debug only /* if (NewTcount > 240) { Serial.println("BUG1"); Tcount = 0; NewTcount = 0; // } if (NewTcount > 39) { // new Serial.println("BUG2"); Tcount = Tcount - 1; NewTcount = NewTcount - 1; // } */ OldTcount = NewTcount; display.clearDisplay(); display.setCursor(10, 4); if (NewTcount < 10) { display.print("0"); //Serial.print("0"); } display.print(NewTcount); display.display(); Serial.print(" TK"); Serial.println(NewTcount); } } // For ATmega328 AVR only ISR (PCINT2_vect) { // Another thing, during the execution of an interrupt, Arduino does not update the value of the millis and micros function. // So, the execution time of the ISR is not counted and the Arduino has a time lag. // You can use the millis and micros function to count time between two interrupts. // But during the interruption the time is not updated. // For PCINT of pins D0 a D7 // int NS03 if (digitalRead(5) == HIGH) { timeNS03 = micros(); D5_state = true; #if DEBUG Serial.print(" +N3sh:"); Serial.print(timeNS03); Serial.print(" N2sh:"); Serial.print(timeNS02); Serial.print(" N4sh:"); Serial.println(timeNS04); #endif if (timeNS03 < (timeNS02 + 1200)) { #if DEBUG Serial.println(" --N3sH:"); // #endif if (timeNS04 < (timeNS03 + 40000)) { Tcount --; } } } else if (digitalRead(5) == LOW) { timeNS03 = micros(); D5_state = false; #if DEBUG Serial.print(" -N3sl:"); Serial.print(timeNS03); Serial.print(" N4s:"); Serial.println(timeNS04); #endif if (timeNS03 < timeNS04 + 600 ) { #if DEBUG Serial.print (" --N3sL "); Serial.print(" N2s:"); Serial.println(timeNS02); #endif Tcount --; if (timeNS03 < timeNS02 + 31200 ) { // 31028 FOWARD Glitch Fix Tcount ++; #if DEBUG Serial.print (" ++N3sL"); #endif } } } } void IRQ_NS02() { digitalWrite(LED_BUILTIN, LOW); timeNS02 = micros(); // only need this for timing. } void IRQ_NS04() { digitalWrite(LED_BUILTIN, HIGH); timeNS04 = micros(); #if DEBUG Serial.print(" N4f: "); Serial.println(timeNS04); #endif if (D5_state == true) { if (timeNS04 < (timeNS03 + 10400)) // 20400 10,152 { Tcount ++; #if DEBUG Serial.println(" ++N4f: "); #endif } } } Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 22, 2023 Share Posted October 22, 2023 🙂 20231022_171354.mp4 2 Quote Link to comment Share on other sites More sharing options...
macsonny Posted October 22, 2023 Author Share Posted October 22, 2023 11 minutes ago, Chri O. said: Ok this need more testing but anyways... Tandon Drive ARDUINO UNO only ATmega328 AVR Pin Change Interrupt in use 🙂 /********************************************************************* MIT License Copyright (c) [2023] [Chris O.] Atari 1050 - Track Display, ver 03. For Tandon Drive. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *********************************************************************/ // https://github.com/wonho-maker/Adafruit_SH1106 /********************************************************************* Change the adafruit SSD1306 to SH1106 SH1106 driver don't provide several functions such as scroll commands. *********************************************************************/ // Teensy SH1106 driver fix https://forum.pjrc.com/threads/68174-OLED-problems #pragma message("Tandon Drive ARDUINO UNO only ATmega328 AVR Pin Change Interrupt in use") #define DEBUG 0 // Serial(115200) SET TO 0 REMOVE DEBUG, 1 DEBUG ON const byte VER = 03; // NOTE: It is a good idea to connect OUTPUT-INPUT pins to other devices with // 470ohm or 1k resistors for Short circuit current-limiting. // ARDUINO UNO const byte interruptPin_NS01 = 4; // NS01 @ U2 ic pin 2, NOT USED FOR interrupt. const byte interruptPin_NS02 = 2; // NS02 @ U2 ic pin 7 Hardware interrupt. const byte interruptPin_NS03 = 5; // NS03 @ U3 ic pin 2 For PCINT interrupt. PCINT21 -- ATmega328 const byte interruptPin_NS04 = 3; // NS04 @ U3 ic pin 7 Hardware interrupt. const byte N_TRACK00_Pin = 6; // Look for Q5 and C47,C50 on 1050 motherboard // connect closer to the C47,C50 side @ R#59 Track 00 sensor. // // MCU GND to 1050 TP15 GND (test point 15). // Optional +5v available @ 1050 TP13. // ATmega328 AVR HACK, PCINT pin change interrupt bool D4_state = false; bool D5_state = false; volatile byte Tcount = 0; volatile unsigned long timeNS01 = 0; // PCINT pin change interrupt TIME volatile unsigned long timeNS02 = 0; volatile unsigned long timeNS03 = 0; // PCINT pin change interrupt TIME volatile unsigned long timeNS04 = 0; bool received = false; // byte NewTcount = Tcount; byte OldTcount = Tcount; #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> //TODO #include <Adafruit_SSD1306> // 0.91 Inch I2C OLED Display #include <Adafruit_SH1106.h> // OLED 1.30" @ I2C addr. 0x3C #define OLED_RESET -1 // -1, NO RESET Adafruit_SH1106 display(OLED_RESET); #define LOGO16_GLCD_HEIGHT 16 #define LOGO16_GLCD_WIDTH 16 static const unsigned char PROGMEM logo16_glcd_bmp[] = { B00000000, B11000000, B00000001, B11000000, B00000001, B11000000, B00000011, B11100000, B11110011, B11100000, B11111110, B11111000, B01111110, B11111111, B00110011, B10011111, B00011111, B11111100, B00001101, B01110000, B00011011, B10100000, B00111111, B11100000, B00111111, B11110000, B01111100, B11110000, B01110000, B01110000, B00000000, B00110000 }; void setup() { // put your setup code here, to run once: Serial.begin(115200); while (!Serial && millis() < 4000 ); Serial.print("Basic ARDUINO UNO 1050(For Tandon Drive) Test: v.0"); Serial.println(VER); // SH1106 driver display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64), SH1106 addr 0x3C. display.SH1106_command(0X81); // SETCONTRAST display.SH1106_command(255); // VALUE 0 TO 255 // Show image buffer on the display hardware. // Since the buffer is intialized with an Adafruit splashscreen // internally, this will display the splashscreen. display.display(); delay(1000); // Clear the buffer. display.clearDisplay(); // Show the display buffer on the hardware. // NOTE: You _must_ call display after making any drawing commands // to make them visible on the display hardware! display.display(); display.setTextSize(2); // display.setTextColor(WHITE); display.setTextColor(BLACK, WHITE); // 'inverted' text display.setCursor(0, 5); display.println("Atari 1050"); // display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(10, 30); display.println("Track Display Test"); // display.setCursor(10, 55); display.print("V.0"); display.println(VER); display.display(); // display setup for loop() display.clearDisplay(); display.setCursor(5, 5); display.setTextSize(9); delay(1000); if (NewTcount < 10) { display.print("0"); } display.print(NewTcount); display.display(); display.SH1106_command(0X81); // SETCONTRAST display.SH1106_command(50); // CONTRAST VALUE 0 TO 255 pinMode(LED_BUILTIN, OUTPUT); // NOTE: on UNO pin 13 pinMode(N_TRACK00_Pin, INPUT_PULLUP); pinMode(interruptPin_NS01, INPUT_PULLUP); pinMode(interruptPin_NS02, INPUT_PULLUP); // edge-triggered interrupt on rising edge (low to high). attachInterrupt(digitalPinToInterrupt(interruptPin_NS02), IRQ_NS02, FALLING); //RISING, CHANGE, FALLING pinMode(interruptPin_NS03, INPUT_PULLUP); pinMode(interruptPin_NS04, INPUT_PULLUP); // edge-triggered interrupt on rising edge (low to high). attachInterrupt(digitalPinToInterrupt(interruptPin_NS04), IRQ_NS04, RISING); //RISING, CHANGE, FALLING // For ATmega328 AVR ONLY, PCINT Pin Change Interrupt PCICR |= B00000100; //Bit2 = 1 -> "PCIE2" enabeled (PCINT16 to PCINT23) PCMSK2 |= B00100000; //Bit5 = 1 -> "PCINT21" enabeled } void loop() { // put your main code here, to run repeatedly: noInterrupts(); NewTcount = Tcount; interrupts(); if (digitalRead(N_TRACK00_Pin) == HIGH) { // if Track 0 sensor @5volts then set TRACK count to 0 NewTcount = 0; noInterrupts(); Tcount = 0; interrupts(); received = false; } if (OldTcount != NewTcount) { // for debug only /* if (NewTcount > 240) { Serial.println("BUG1"); Tcount = 0; NewTcount = 0; // } if (NewTcount > 39) { // new Serial.println("BUG2"); Tcount = Tcount - 1; NewTcount = NewTcount - 1; // } */ OldTcount = NewTcount; display.clearDisplay(); display.setCursor(10, 4); if (NewTcount < 10) { display.print("0"); //Serial.print("0"); } display.print(NewTcount); display.display(); Serial.print(" TK"); Serial.println(NewTcount); } } // For ATmega328 AVR only ISR (PCINT2_vect) { // Another thing, during the execution of an interrupt, Arduino does not update the value of the millis and micros function. // So, the execution time of the ISR is not counted and the Arduino has a time lag. // You can use the millis and micros function to count time between two interrupts. // But during the interruption the time is not updated. // For PCINT of pins D0 a D7 // int NS03 if (digitalRead(5) == HIGH) { timeNS03 = micros(); D5_state = true; #if DEBUG Serial.print(" +N3sh:"); Serial.print(timeNS03); Serial.print(" N2sh:"); Serial.print(timeNS02); Serial.print(" N4sh:"); Serial.println(timeNS04); #endif if (timeNS03 < (timeNS02 + 1200)) { #if DEBUG Serial.println(" --N3sH:"); // #endif if (timeNS04 < (timeNS03 + 40000)) { Tcount --; } } } else if (digitalRead(5) == LOW) { timeNS03 = micros(); D5_state = false; #if DEBUG Serial.print(" -N3sl:"); Serial.print(timeNS03); Serial.print(" N4s:"); Serial.println(timeNS04); #endif if (timeNS03 < timeNS04 + 600 ) { #if DEBUG Serial.print (" --N3sL "); Serial.print(" N2s:"); Serial.println(timeNS02); #endif Tcount --; if (timeNS03 < timeNS02 + 31200 ) { // 31028 FOWARD Glitch Fix Tcount ++; #if DEBUG Serial.print (" ++N3sL"); #endif } } } } void IRQ_NS02() { digitalWrite(LED_BUILTIN, LOW); timeNS02 = micros(); // only need this for timing. } void IRQ_NS04() { digitalWrite(LED_BUILTIN, HIGH); timeNS04 = micros(); #if DEBUG Serial.print(" N4f: "); Serial.println(timeNS04); #endif if (D5_state == true) { if (timeNS04 < (timeNS03 + 10400)) // 20400 10,152 { Tcount ++; #if DEBUG Serial.println(" ++N4f: "); #endif } } } Fantastic! Any chance you can take some photos of the actual Arduino board and also the floppy drive main board to see exact wiring points? Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 22, 2023 Share Posted October 22, 2023 // ARDUINO UNO Pin NS01 = 4; // NS01 @ U2 ic pin 2, NOT USED FOR interrupt. Pin NS02 = 2; // NS02 @ U2 ic pin 7 Hardware interrupt. Pin NS03 = 5; // NS03 @ U3 ic pin 2 For PCINT interrupt. PCINT21 -- ATmega328 Pin NS04 = 3; // NS04 @ U3 ic pin 7 Hardware interrupt. N_TRACK00 Pin = 6; Look for Q5 and C47,C50 on 1050 motherboard connect closer to the C47,C50 side @ R#59 Track 00 sensor. ARDUINO UNO GND to 1050 TP15 GND (test point 15). !!!! Optional +5v available @ 1050 TP13. Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 22, 2023 Share Posted October 22, 2023 TRK.00 ang GND TP15 Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 22, 2023 Share Posted October 22, 2023 Quote Link to comment Share on other sites More sharing options...
macsonny Posted October 23, 2023 Author Share Posted October 23, 2023 5 hours ago, Chri O. said: Thank you! Quote Link to comment Share on other sites More sharing options...
Mathy Posted October 23, 2023 Share Posted October 23, 2023 Hello @Chri O. Now alll you have to do is find a (seven segment?) display that fits where the power switch usually sits. And that leaves room for a push switch where the power LED sits. Sincerely Mathy Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 24, 2023 Share Posted October 24, 2023 I2C 0.96-inch OLED Display SSD1306 128x64 Pixels IIC 3.3V 5V White just ordered coming on my way. The one I was using was 1.30-inch. 1 Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 24, 2023 Share Posted October 24, 2023 I am working on new firmware ver04 with the ability of selecting the library (Adafruit_SSD1306 - Adafruit_SH1106) and OLED screen Auto dimming. Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 24, 2023 Share Posted October 24, 2023 Spoiler /********************************************************************* MIT License Copyright (c) [2023] [Chris O.] Atari 1050 - Track Display, ver 04. For Tandon Drive. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *********************************************************************/ const byte VER = 04; #pragma message("Tandon Drive ARDUINO UNO only ATmega328 AVR Pin Change Interrupt in use") // -------------------------------------------------------------------------------------------------------------- // -- Adjust as you like here ----------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------- #define DEBUG 0 // Serial(115200) SET TO 0 REMOVE DEBUG, 1 DEBUG ON // -- #define SetLib 1 // ---> 1 Adafruit_SSD1306, ---> 0 Adafruit_SH1106. // -- #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN_ADDRESS 0x3D //<- // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32, 1.31 128x64 SH1106 addr 0x3C. // -- // OLED Auto-dimming unsigned long interval = 10000; // 10sec const byte ContrastValueMAX = 0x7F; // MAX 127 see datasheet https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf // -------------------------------------------------------------------------------------------------------------- unsigned long preMillis = 0; byte ContrastValue = ContrastValueMAX; volatile byte curContrastValue = ContrastValueMAX; // NOTE: It is a good idea to connect OUTPUT-INPUT pins to other devices with // 470ohm or 1k resistors for Short circuit current-limiting. // ARDUINO UNO const byte interruptPin_NS01 = 4; // NS01 @ U2 ic pin 2, NOT USED FOR interrupt. const byte interruptPin_NS02 = 2; // NS02 @ U2 ic pin 7 Hardware interrupt. const byte interruptPin_NS03 = 5; // NS03 @ U3 ic pin 2 For PCINT interrupt. PCINT21 -- ATmega328 const byte interruptPin_NS04 = 3; // NS04 @ U3 ic pin 7 Hardware interrupt. const byte N_TRACK00_Pin = 6; // Look for Q5 and C47,C50 on 1050 motherboard // connect closer to the C47,C50 side @ R#59 Track 00 sensor. // // MCU GND to 1050 TP15 GND (test point 15). // Optional +5v available @ 1050 TP13. // ATmega328, PCINT pin change interrupt bool D5_state = false; volatile byte Tcount = 0; volatile unsigned long timeNS01 = 0; // volatile unsigned long timeNS02 = 0; volatile unsigned long timeNS03 = 0; // PCINT pin change interrupt TIME volatile unsigned long timeNS04 = 0; byte NewTcount = Tcount; byte OldTcount = Tcount; // https://github.com/wonho-maker/Adafruit_SH1106 /********************************************************************* Change the adafruit SSD1306 to SH1106 SH1106 driver don't provide several functions such as scroll commands. *********************************************************************/ // Teensy SH1106 driver fix https://forum.pjrc.com/threads/68174-OLED-problems #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #if SetLib // SSD1306 driver #include <Adafruit_SSD1306.h> // 0.91 Inch I2C OLED Display or 0.96" OLED Module I2C. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); #else // SH1106 driver #include <Adafruit_SH1106.h> // OLED 1.30" @ I2C addr. 0x3C Adafruit_SH1106 display(OLED_RESET); #endif #define LOGO16_GLCD_HEIGHT 16 #define LOGO16_GLCD_WIDTH 16 static const unsigned char PROGMEM logo16_glcd_bmp[] = { B00000000, B11000000, B00000001, B11000000, B00000001, B11000000, B00000011, B11100000, B11110011, B11100000, B11111110, B11111000, B01111110, B11111111, B00110011, B10011111, B00011111, B11111100, B00001101, B01110000, B00011011, B10100000, B00111111, B11100000, B00111111, B11110000, B01111100, B11110000, B01110000, B01110000, B00000000, B00110000 }; // ------------------------------------------------------------------------------------------------------------------------------- void setup() { // put your setup code here, to run once: Serial.begin(115200); while (!Serial && millis() < 2000 ); Serial.print("Basic ARDUINO UNO 1050(For Tandon Drive) Test: v.0"); Serial.println(VER); #if SetLib // SSD1306 driver if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for (;;); // Don't proceed, loop forever } display.ssd1306_command(0X81); // SETCONTRAST display.ssd1306_command(ContrastValueMAX); // 0 to 127 // Show image buffer on the display hardware. // Since the buffer is intialized with an Adafruit splashscreen // internally, this will display the splashscreen. display.display(); delay(1000); // Clear the buffer. display.clearDisplay(); // Show the display buffer on the hardware. // NOTE: You _must_ call display after making any drawing commands // to make them visible on the display hardware! display.display(); display.setTextSize(2); // display.setTextColor(WHITE); display.setTextColor(BLACK, WHITE); // 'inverted' text display.setCursor(0, 5); display.println("Atari 1050"); // display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(10, 30); display.println("Track Display Test"); // display.setCursor(10, 55); display.print("V.0"); display.println(VER); display.display(); delay(1000); // display setup for loop() display.clearDisplay(); display.setCursor(10, 4); display.setTextSize(9); if (NewTcount < 10) { display.print("0"); } display.print(NewTcount); display.display(); #else // // SH1106 driver display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64), SH1106 addr 0x3C. // display.begin(SH1106_SWITCHCAPVCC, SCREEN_ADDRESS); // 127 max ? see datasheet https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf display.SH1106_command(0X81); // SETCONTRAST display.SH1106_command(ContrastValueMAX); // Show image buffer on the display hardware. // Since the buffer is intialized with an Adafruit splashscreen // internally, this will display the splashscreen. display.display(); delay(1000); // Clear the buffer. display.clearDisplay(); // Show the display buffer on the hardware. // NOTE: You _must_ call display after making any drawing commands // to make them visible on the display hardware! display.display(); display.setTextSize(2); // display.setTextColor(WHITE); display.setTextColor(BLACK, WHITE); // 'inverted' text display.setCursor(0, 5); display.println("Atari 1050"); // display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(10, 30); display.println("Track Display Test"); // display.setCursor(10, 55); display.print("V.0"); display.println(VER); display.display(); delay(1000); // display setup for loop() display.clearDisplay(); display.setCursor(10, 4); display.setTextSize(9); if (NewTcount < 10) { display.print("0"); } display.print(NewTcount); display.display(); #endif pinMode(LED_BUILTIN, OUTPUT); // NOTE: on UNO pin 13 pinMode(12, OUTPUT); // 2ND LED pin 12 pinMode(N_TRACK00_Pin, INPUT_PULLUP); pinMode(interruptPin_NS01, INPUT_PULLUP); pinMode(interruptPin_NS02, INPUT_PULLUP); // edge-triggered interrupt on rising edge (low to high). attachInterrupt(digitalPinToInterrupt(interruptPin_NS02), IRQ_NS02, FALLING); //RISING, CHANGE, FALLING pinMode(interruptPin_NS03, INPUT_PULLUP); pinMode(interruptPin_NS04, INPUT_PULLUP); // edge-triggered interrupt on rising edge (low to high). attachInterrupt(digitalPinToInterrupt(interruptPin_NS04), IRQ_NS04, RISING); //RISING, CHANGE, FALLING // For ATmega328 AVR ONLY, PCINT Pin Change Interrupt PCICR |= B00000100; //Bit2 = 1 -> "PCIE2" enabeled (PCINT16 to PCINT23) PCMSK2 |= B00100000; //Bit5 = 1 -> "PCINT21" enabeled } // ------------------------------------------------------------------------------------------------------------------------------- void loop() { // put your main code here, to run repeatedly: noInterrupts(); NewTcount = Tcount; interrupts(); OLED_CONTRAST(); // Oled Auto-dimming if (digitalRead(N_TRACK00_Pin) == HIGH) { // if Track 0 sensor @5volts then set TRACK count to 0 NewTcount = 0; noInterrupts(); Tcount = 0; interrupts(); } if (OldTcount != NewTcount) { // for debug only /* if (NewTcount > 240) { Serial.println("BUG1"); Tcount = 0; NewTcount = 0; // } if (NewTcount > 39) { // new Serial.println("BUG2"); Tcount = Tcount - 1; NewTcount = NewTcount - 1; // } */ OldTcount = NewTcount; display.clearDisplay(); display.setCursor(10, 4); if (NewTcount < 10) { display.print("0"); //Serial.print("0"); } display.print(NewTcount); display.display(); Serial.print(" TK"); Serial.println(NewTcount); unsigned long curMillis = millis(); preMillis = curMillis; //for OLED Auto-dimming } } // ------ OLED Auto-dimming------------------------------------------------------------------------------------------------------- void OLED_CONTRAST() { unsigned long curMillis = millis(); if (curMillis - preMillis >= interval) { preMillis = curMillis; ContrastValue = 0; // MIN contrast. curContrastValue = 0; #if SetLib // SSD1306 driver display.ssd1306_command(0X81); // SETCONTRAST display.ssd1306_command(ContrastValue); #else // // SH1106 driver display.SH1106_command(0X81); display.SH1106_command(ContrastValue); #endif Serial.println(" OLED Auto-dimming"); } if (ContrastValue != curContrastValue) { ContrastValue = curContrastValue; #if SetLib // SSD1306 driver display.ssd1306_command(0X81); // SETCONTRAST display.ssd1306_command(curContrastValue); #else // // SH1106 driver display.SH1106_command(0X81); display.SH1106_command(curContrastValue); #endif } } // ------------------------------------------------------------------------------------------------------------------------------- // For ATmega328 AVR only ISR (PCINT2_vect) { // Another thing, during the execution of an interrupt, Arduino does not update the value of the millis and micros function. // So, the execution time of the ISR is not counted and the Arduino has a time lag. // You can use the millis and micros function to count time between two interrupts. // But during the interruption the time is not updated. // For PCINT of pins D0 a D7 // int NS03 if (digitalRead(5) == HIGH) { timeNS03 = micros(); D5_state = true; #if DEBUG Serial.print(" +N3sh:"); Serial.print(timeNS03); Serial.print(" N2sh:"); Serial.print(timeNS02); Serial.print(" N4sh:"); Serial.println(timeNS04); #endif if (timeNS03 < (timeNS02 + 1200)) { #if DEBUG Serial.println(" --N3sH:"); // #endif if (timeNS04 < (timeNS03 + 40000)) { Tcount --; } } } else if (digitalRead(5) == LOW) { timeNS03 = micros(); D5_state = false; #if DEBUG Serial.print(" -N3sl:"); Serial.print(timeNS03); Serial.print(" N4s:"); Serial.println(timeNS04); #endif if (timeNS03 < timeNS04 + 600 ) { #if DEBUG Serial.print (" --N3sL "); Serial.print(" N2s:"); Serial.println(timeNS02); #endif Tcount --; if (timeNS03 < timeNS02 + 31200 ) { // 31028 FOWARD Glitch Fix Tcount ++; #if DEBUG Serial.print (" ++N3sL"); #endif } } } } void IRQ_NS02() { digitalWrite(LED_BUILTIN, LOW); // 1st led digitalWrite(12, HIGH); // 2nd led timeNS02 = micros(); // only need this for timing. curContrastValue = ContrastValueMAX; } void IRQ_NS04() { digitalWrite(LED_BUILTIN, HIGH); // 1st led digitalWrite(12, LOW); // 2nd led timeNS04 = micros(); curContrastValue = ContrastValueMAX; #if DEBUG Serial.print(" N4f: "); Serial.println(timeNS04); #endif if (D5_state == true) { if (timeNS04 < (timeNS03 + 10400)) // 20400 10,152 { Tcount ++; #if DEBUG Serial.println(" ++N4f: "); #endif } } } Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 24, 2023 Share Posted October 24, 2023 For the curious this is how I'm going to attach the new display they should be a bit smaller. Ignore this tensioner 😁 Quote Link to comment Share on other sites More sharing options...
macsonny Posted October 24, 2023 Author Share Posted October 24, 2023 21 minutes ago, Chri O. said: For the curious this is how I'm going to attach the new display they should be a bit smaller. Ignore this tensioner 😁 I like the idea of a tensioner though! Quote Link to comment Share on other sites More sharing options...
xrbrevin Posted October 25, 2023 Share Posted October 25, 2023 great work! but is a pico or nano viable instead of the uno? they are easier to accommodate Quote Link to comment Share on other sites More sharing options...
macsonny Posted October 25, 2023 Author Share Posted October 25, 2023 (edited) So question. I have already upgraded all my TANDON drives with MegaSpeedy that has the LED track display already. I have two World Drives. One has a Happy upgrade and the other is stock. How would your code for the track display differ for a World Drive mechanism? Edited October 25, 2023 by macsonny Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted October 25, 2023 Share Posted October 25, 2023 (edited) 3 hours ago, xrbrevin said: great work! but is a pico or nano viable instead of the uno? they are easier to accommodate Have a look at this much earlier in this thread, unfortunately, not had time to get much further, using a Pico Edited October 25, 2023 by TGB1718 Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 25, 2023 Share Posted October 25, 2023 8 hours ago, xrbrevin said: great work! but is a pico or nano viable instead of the uno? they are easier to accommodate Arduino Nano should work right out of the box it is basically using the same MCU ATmega328P-MUR as Arduino UNO. Quote Link to comment Share on other sites More sharing options...
xrbrevin Posted October 25, 2023 Share Posted October 25, 2023 2 hours ago, Chri O. said: Arduino Nano should work right out of the box it is basically using the same MCU ATmega328P-MUR as Arduino UNO. cheers, i have a few of those and a smaller OLED (as used in goteks) so i'll have a build in the next few days and let you know how it goes 🤔 1 Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 25, 2023 Share Posted October 25, 2023 🙂 0.96 I2C OLED Well I was under the impression I need adafruit SSD1306 library for this display but it needs Adafruit_SH1106 library. 2 Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 25, 2023 Share Posted October 25, 2023 Quick and easy installation using 3M double sided tape. 20231025_160032.mp4 3 Quote Link to comment Share on other sites More sharing options...
macsonny Posted October 26, 2023 Author Share Posted October 26, 2023 8 hours ago, Chri O. said: Quick and easy installation using 3M double sided tape. 20231025_160032.mp4 60.74 MB · 0 downloads Nice work! Not sure you saw my question above - will this solution for track display also work on the World Drive version of the floppy drives? Quote Link to comment Share on other sites More sharing options...
Chri O. Posted October 26, 2023 Share Posted October 26, 2023 Yes and No .. 😁 For World Drive use this firmware v01 I posted this about year ago on page #4. This is using the same wiring connection for arduino uno so you just need to flush different firmware. On 5/10/2022 at 12:58 PM, Chri O. said: Arduino uno code. /********************************************************************* MIT License Copyright (c) [2022] [Chris O.] Atari 1050 - Track Display, ver 01. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *********************************************************************/ // https://github.com/wonho-maker/Adafruit_SH1106 /********************************************************************* Change the adafruit SSD1306 to SH1106 SH1106 driver don't provide several functions such as scroll commands. *********************************************************************/ // Teensy SH1106 driver fix https://forum.pjrc.com/threads/68174-OLED-problems const byte VER = 2; // ARDUINO UNO const byte interruptPin_NS01 = 4; // NS01 @ U2 ic pin 2, NOT USED FOR interrupt. const byte interruptPin_NS02 = 2; // NS02 @ U2 ic pin 7 const byte interruptPin_NS03 = 5; // NS03 @ U3 ic pin 2 NOT USED FOR interrupt. const byte interruptPin_NS04 = 3; // NS04 @ U3 ic pin 7 const byte N_TRACK00_Pin = 6; // Q5 @ R#59 Track 00 sensor. /* // TEENSY 4.0 const byte interruptPin_NS01 = 2; // NS01 @ U2 ic pin 2, NOT USED FOR interrupt. const byte interruptPin_NS02 = 3; // NS02 @ U2 ic pin 7 const byte interruptPin_NS03 = 4; // NS03 @ U3 ic pin 2 NOT USED FOR interrupt. const byte interruptPin_NS04 = 5; // NS04 @ U3 ic pin 7 const byte N_TRACK00_Pin = 6; // Q5 @ R#59 Track 00 sensor. */ volatile byte Tcount = 0; byte NewTcount = Tcount; byte OldTcount = Tcount; #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SH1106.h> // OLED 1.30" @ I2C addr. 0x3C #define OLED_RESET -1 // -1, NO RESET Adafruit_SH1106 display(OLED_RESET); #define LOGO16_GLCD_HEIGHT 16 #define LOGO16_GLCD_WIDTH 16 static const unsigned char PROGMEM logo16_glcd_bmp[] = { B00000000, B11000000, B00000001, B11000000, B00000001, B11000000, B00000011, B11100000, B11110011, B11100000, B11111110, B11111000, B01111110, B11111111, B00110011, B10011111, B00011111, B11111100, B00001101, B01110000, B00011011, B10100000, B00111111, B11100000, B00111111, B11110000, B01111100, B11110000, B01110000, B01110000, B00000000, B00110000 }; void setup() { // put your setup code here, to run once: Serial.begin(115200); while (!Serial && millis() < 4000 ); Serial.println("Basic ARDUINO UNO 1050 Test:"); display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64), SH1106 addr 0x3C. // Show image buffer on the display hardware. // Since the buffer is intialized with an Adafruit splashscreen // internally, this will display the splashscreen. display.display(); delay(1000); // Clear the buffer. display.clearDisplay(); // Show the display buffer on the hardware. // NOTE: You _must_ call display after making any drawing commands // to make them visible on the display hardware! display.display(); display.setTextSize(2); // display.setTextColor(WHITE); display.setTextColor(BLACK, WHITE); // 'inverted' text display.setCursor(0, 5); display.println("Atari 1050"); // display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(10, 30); display.println("Track Display Test"); // display.setCursor(10, 55); display.print("V.0"); display.println(VER); display.display(); // display setup for loop() display.clearDisplay(); display.setCursor(5, 5); display.setTextSize(9); delay(1000); if (NewTcount < 10) { display.print("0"); } display.print(NewTcount); display.display(); //pinMode(ledPin, OUTPUT); pinMode(N_TRACK00_Pin, INPUT_PULLUP); pinMode(interruptPin_NS01, INPUT_PULLUP); pinMode(interruptPin_NS02, INPUT_PULLUP); // edge-triggered interrupt on rising edge (low to high). attachInterrupt(digitalPinToInterrupt(interruptPin_NS02), IRQ_NS02, RISING); //RISING, CHANGE, FALLING pinMode(interruptPin_NS03, INPUT_PULLUP); pinMode(interruptPin_NS04, INPUT_PULLUP); // edge-triggered interrupt on rising edge (low to high). attachInterrupt(digitalPinToInterrupt(interruptPin_NS04), IRQ_NS04, RISING); //RISING, CHANGE, FALLING } void loop() { // put your main code here, to run repeatedly: noInterrupts(); NewTcount = Tcount; interrupts(); if (digitalRead(N_TRACK00_Pin) == HIGH) { // if Track 0 sensor @5volts then set TRACK count to 0 NewTcount = 0; //noInterrupts(); //Tcount = 0; //interrupts(); } if (OldTcount != NewTcount) { OldTcount = NewTcount; display.clearDisplay(); display.setCursor(10, 4); if (NewTcount < 10) { display.print("0"); Serial.print("0"); } display.print(NewTcount); display.display(); Serial.println(NewTcount); } } void IRQ_NS02() { digitalWrite(LED_BUILTIN, LOW); if (digitalRead(interruptPin_NS01) == HIGH) { Tcount ++; } else { Tcount --; } //digitalWrite(LED_BUILTIN, LOW); //Serial.print("T NS02 :"); // debug print //Serial.println(Tcount); // debug print } void IRQ_NS04() { digitalWrite(LED_BUILTIN, LOW); if (digitalRead(interruptPin_NS03) == HIGH) { Tcount ++; } else { Tcount --; } //digitalWrite(LED_BUILTIN, LOW); //Serial.print("T NS04 :"); // debug print //Serial.println(Tcount); // debug print } Quote Link to comment Share on other sites More sharing options...
macsonny Posted October 26, 2023 Author Share Posted October 26, 2023 I'm fairly happy with the results. Seems to work fine so far - but it's a counter so if the drive gets out of synch for some reason you'll get odd track counts. Still, seems to work fine in my Happy drive 🙂 IMG_3818.mov 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.