no-software internal RTC
Re: no-software internal RTC
Today I've discovered two things:
1) bit-mask for reading hour from ds3231 is 1 bit too short, and essentially unnecessary,
2) on TOS 1.62 it is not the CONTROL.ACC what polls the IKBD clock, but... STE_FIX.PRG (despite it is only for TOS 1.06, and here it displays that it is not required for this TOS).
1) bit-mask for reading hour from ds3231 is 1 bit too short, and essentially unnecessary,
2) on TOS 1.62 it is not the CONTROL.ACC what polls the IKBD clock, but... STE_FIX.PRG (despite it is only for TOS 1.06, and here it displays that it is not required for this TOS).
Re: no-software internal RTC
Last update (hope so).
For TOS 1.x it requires STE_FIX to work, so it only works on STe with TOS 1.06 and 1.62. On TOS 2.06 it doesn't require any software, so it should work on any ST running this version of TOS.
Code after clean up:
Explanation why it works - IKBD firmware has a "smart" BCD (de)coding routine, thus ignores any input that has a "halfbyte" value higher than 9, yet TOS has a "dumb" BCD (de)coding routine, which makes it accept any value. What is more, values like 0xA0 are correctly interpreted as 100. Atari programmers were obviously aware of this "feature", and that's why their control panel returns correct BCD values for years 80-99, and "erroneous" BCD for values 00-79* (as 100-179). In conjunction with the way the TOS internally stores the year it all works just fine, but not with the original IKBD.
* - actually I didn't check the year span which is sent as 20xx, and I'm not sure if the control.acc itself is responsible for setting the IKBD clock or, ste_fix.prg installs some clock update handler, to update the IKBD date when TOS date is changed. It is also interesting, why they have included IKBD<->TOS clock synchronization feature in ste_fix.prg, but not in TOS 1.62.
For TOS 1.x it requires STE_FIX to work, so it only works on STe with TOS 1.06 and 1.62. On TOS 2.06 it doesn't require any software, so it should work on any ST running this version of TOS.
Code after clean up:
Code: Select all
/******************************************************************
Created with PROGRAMINO IDE for Arduino - 06.08.2018 15:23:03
Project : Atari ST IKBD clock injector with DS3231 RTC
Libraries : SoftwareSerial, Wire
Author : TzOk
Description : ARD_RX0 from KB_5, ARD_TX1 to ST_5, ARD_D10 from/to KB/ST_6
******************************************************************/
#include <SoftwareSerial.h>
#include <Wire.h>
#define DS3231_ADDRESS (0x68)
#define DS3231_REG_TIME (0x00)
SoftwareSerial Ctrl(10, 11);
byte cmd;
byte inj = 255;
byte dsDate[7];
byte stDate[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC};
// ss, mm, hh, DD, MM, YY
void setup()
{
Serial.begin(7812);
Ctrl.begin(7812);
Ctrl.listen();
Wire.begin();
}
void loop()
{
if (Ctrl.available())
{
cmd = Ctrl.read();
if (cmd == 0x1C) // Read RTC
{
Wire.beginTransmission(DS3231_ADDRESS);
Wire.write(DS3231_REG_TIME);
Wire.endTransmission();
Wire.requestFrom(DS3231_ADDRESS, 7);
while(!Wire.available()) {};
for (byte i = 6; i < 255; i--)
{
dsDate[i] = Wire.read();
}
stDate[5] = (dsDate[1] & 0x80) ? dsDate[0] + 0xA0 : dsDate[0]; // YY : if CENTURY bit is SET => stDate = dsDate + 100
stDate[4] = dsDate[1] & 0x1F; // MM
stDate[3] = dsDate[2]; // DD
stDate[2] = dsDate[4] & 0x3F; // hh
stDate[1] = dsDate[5]; // mm
stDate[0] = dsDate[6]; // ss
inj = 6;
}
else if (cmd == 0x1B) // Set RTC
{
for (byte i = 5; i < 255; i--)
{
while(!Ctrl.available()) {};
stDate[i] = Ctrl.read();
}
dsDate[0] = (stDate[5] < 0xA0) ? stDate[5] : stDate[5] - 0xA0; // YY : if stDate > 99 => dsDate = stDate - 100
dsDate[1] = (stDate[5] < 0xA0) ? stDate[4] : stDate[4] + 0x80; // MM : if stDate > 99 => set CENTURY bit
dsDate[2] = stDate[3]; // DD
dsDate[3] = 0x01; // Day of Week : don't care, any valid value 1-7 will be ok`
dsDate[4] = stDate[2]; // hh
dsDate[5] = stDate[1]; // mm
dsDate[6] = stDate[0]; // ss
Wire.beginTransmission(DS3231_ADDRESS);
Wire.write(DS3231_REG_TIME);
for (byte i = 6; i < 255; i--)
{
Wire.write(dsDate[i]);
}
Wire.endTransmission();
}
}
}
void serialEvent() {
if (inj == 255)
Serial.write(Serial.read());
else
{
Serial.read();
Serial.write(stDate[inj--]);
}
}
* - actually I didn't check the year span which is sent as 20xx, and I'm not sure if the control.acc itself is responsible for setting the IKBD clock or, ste_fix.prg installs some clock update handler, to update the IKBD date when TOS date is changed. It is also interesting, why they have included IKBD<->TOS clock synchronization feature in ste_fix.prg, but not in TOS 1.62.
Re: no-software internal RTC
It is ready...
... and fits inside STe:
Edit by IngoQ: Images scaled and uploaded to forum, high-res pictures available here:
https://obrazki.elektroda.pl/8165213200_1536065036.jpg
https://obrazki.elektroda.pl/2757590500_1536065030.jpg
https://obrazki.elektroda.pl/7399977500_1536065051.jpg
... and fits inside STe:
Edit by IngoQ: Images scaled and uploaded to forum, high-res pictures available here:
https://obrazki.elektroda.pl/8165213200_1536065036.jpg
https://obrazki.elektroda.pl/2757590500_1536065030.jpg
https://obrazki.elektroda.pl/7399977500_1536065051.jpg
Re: no-software internal RTC
If there will be interest I may make a few units, but it was intended to be a DIY project. That is why I'm using a ready to use modules, rather than a custom PCB. It requires an Arduino Mini Pro or Nano V3 (or clone) and a "DS3231 for PI" RTC breakout board. Only very basic soldering skills are required for assembling such device.
Re: no-software internal RTC
I've done some further tests and:
* on STf(m) with TOS 1.00 - 1.04 it works using ST Control Panel (CONTROL.ACC), Panel is used both for synchronizing ST Clock with IKBD Clock on reboot and adjusting the clock,
* on STe with TOS 1.06/1.62 using STE_FIX.PRG and STE Control Panel (CONTROL.ACC), STE_FIX is used for synchronizing ST Clock with IKBD Clock on reboot, Panel is required only for adjusting the clock,
* on STe with TOS 2.06 it works using XControl (XCONTROL.ACC), ST Clock with IKBD Clock on reboot synchronization is done by TOS itself, Panel is required only for adjusting the clock.
* on STf(m) with TOS 1.00 - 1.04 it works using ST Control Panel (CONTROL.ACC), Panel is used both for synchronizing ST Clock with IKBD Clock on reboot and adjusting the clock,
* on STe with TOS 1.06/1.62 using STE_FIX.PRG and STE Control Panel (CONTROL.ACC), STE_FIX is used for synchronizing ST Clock with IKBD Clock on reboot, Panel is required only for adjusting the clock,
* on STe with TOS 2.06 it works using XControl (XCONTROL.ACC), ST Clock with IKBD Clock on reboot synchronization is done by TOS itself, Panel is required only for adjusting the clock.
Re: no-software internal RTC
I've experimentally measured the delay introduced by my ST IKBD RTC module:
For comparison - screen redraw time in color mode is 20ms.
dT = 1.28msFor comparison - screen redraw time in color mode is 20ms.
Re: no-software internal RTC
One more notice - as the internal TOS date format is intact, any software using non-standard methods of reading it will still work correctly (however if using 2-digit year format we may see year 118 for 2018). As TOS stores a year on 7 bits it will work only until 2027.
Re: no-software internal RTC
Update.
I was apparently wrong with 2027 as being the last possible to set date. It is 7 bytes in TOS, but 7 bytes from 1980, not from 1900. So the limit is F9 for pseudo-BCD year, which gives 2059. I have verified it in practice.
I was apparently wrong with 2027 as being the last possible to set date. It is 7 bytes in TOS, but 7 bytes from 1980, not from 1900. So the limit is F9 for pseudo-BCD year, which gives 2059. I have verified it in practice.
Re: no-software internal RTC
Next update to keep all RTC related info in one place.
It is not the CONTROL.ACC responsible for setting the IKBD date/time. It adjusts just the GEMDOS clock, but since TOS 1.02 GEMDOS Tsettime() function also sets the XBIOS time, and hence updates the IKBD clock.
Often seen year 28 (2028) is a result of reading a year from unmodified IKBD. If you have something running in the background that polls the XBIOS/IKBD for date/time, you will end up with year 2028. Uninitialized IKBD will always return year C8, and it would reject initialization with anything higher than 99. Polling IKBD clock on reboot is TOS dependent, and actually only 2.06 does that without any software. GEMDOS Tsettime() routine is Y2K compliant, and if you try to set year 19 using Control Panel, it would actually send a correct value 0xB9 (119 which corresponds to 2019) to the IKBD RTC. Yet the IKBD will reject that and stay uninitialized (only for year part, rest of fields will be accepted).
It is not the CONTROL.ACC responsible for setting the IKBD date/time. It adjusts just the GEMDOS clock, but since TOS 1.02 GEMDOS Tsettime() function also sets the XBIOS time, and hence updates the IKBD clock.
Often seen year 28 (2028) is a result of reading a year from unmodified IKBD. If you have something running in the background that polls the XBIOS/IKBD for date/time, you will end up with year 2028. Uninitialized IKBD will always return year C8, and it would reject initialization with anything higher than 99. Polling IKBD clock on reboot is TOS dependent, and actually only 2.06 does that without any software. GEMDOS Tsettime() routine is Y2K compliant, and if you try to set year 19 using Control Panel, it would actually send a correct value 0xB9 (119 which corresponds to 2019) to the IKBD RTC. Yet the IKBD will reject that and stay uninitialized (only for year part, rest of fields will be accepted).