-
TI-86 OBDing Revisited
03/11/2023 at 21:25 • 0 commentsI started peeking back into my TI-86 OBD-reader yesterday... Van's acting-up again, a little. I was surprisingly far with it, already able to send-then-receive via the bitbanged UART, but it's a weird path I went down...
Thing is, my van has two of the many possible OBD2 protocols... One allegedly invented by the manufacturer, the other allegedly never even used in vehicles by this manufacturer(?!). The former has data going constantly. But it's far too fast to be processed in realtime with my bitbanging. In fact, it's so fast the ons and offs are only registerable if I use the tightest loop possible, using the dedicated "sample input, store in memory, repeat" instruction. So, even though there's a complementary "write-output from memory, repeat" instruction, bitbanging output is basically not an option, because the protocol also requires monitoring the bus for collisions *while* transmitting.
Weirdly, as far as I can tell, the system components are nearly exclusively wired directly, not via a serial bus of any sort. So, I don't understand why there's so much chatter on that serial bus. There's one weird exception, which frankly makes little sense. It seems the analog output of the oil-pressure sensor feeds directly into the dashboard circuitry, wherein there's a microcontroller used to drive the stepper-motor for the oil-pressure needle. LOL. Why not just use a standard analog gauge? I *think* it's to do with the sensor's not actually outputting analog at all, it seems to be merely off and on. So, then, I guess the microcontroller interprets pulses (caused by fluctuations in oil pressure? Where do those come from? Something to do with the movement of cams?) and tries to convert those pulses into an analog-ish reading. But information on the matter is weird. Some claim the gauge actually does nothing but show if there is no oil pressure, that it simply sits at some arbitrary position unless it's too low, then sits in the red and turns on the light. Weird. But why's this relevant? Because as far as I can tell, that microcontroller also talks via serial to the computer... but since all the other gauges are directly-wired, it seems to suggest the high-speed "bus" is only communicating oil-pressure readings to the computer! And that, it would seem, is the /only/ chatter on the bus(?!) and a lot of it!
Anyhow, the other serial bus is silent. Which makes more sense for a "request-then-response" protocol like OBD...
So, basically, I wrote my entire TI-86 assembly program and libraries (over nearly a year) based on the presumption that that bus was "the one", which it turns out is a bus nowhere-I've-seen documented as ever being used by my vehicle's manufacturer. Heh.
So far I don't even know enough detail about the packet-protocol... And experimenting with that, in assembly, would be quite an ordeal. Especially if there's no No-Acknowledge if I get something wrong (like the "address" of the computer, or the CRC algorithm, or the header bytes).
So, really, I put a HUGE effort, over nearly a year, into something that may give zero indication that it never would've worked in the first place (e.g. again, why would this bus even be implemented by this manufacturer? I mean, the pins and idle-voltage are there, which is weird-enough).
And, then, the fact is that if it does work in this system, I could've saved myself (could still) a *ton* of effort by programming it in C on a fast computer, where data logging is an option.
I really have no idea what I was thinking doing all that in assembly on a tiny screen with a tiny RAM and awkward "keyboard."
But: After stepping away for a year or more, I was able to compile my old code without a hitch (I think I swapped the batteries once or twice in the meantime)... And, I guess, if my presumption that that bus is usable is actually true, then it's really only a tiny matter to actually try a request and see if there's a response. The request-response mechanism is already implemented, the UART bitbanging already functions, the bitbang timing is already measured from the chatter on the other bus. At this point, It's just the matter of figuring out how to formulate that request. Who knows, maybe it will NAK if I got it wrong, and I'll at least know I'm not barking up the wrongest tree.
So, why not try it? Heh. (Why didn't I way back when?)
-
TI-CBL
07/21/2022 at 06:25 • 0 commentsBack in college physics I'da never thought owning a CBL would be in my future!
Working on #Z80 Reverse-Engineering And Hacking Adventures, I had a weird epiphany... Ordering some chip sockets to solder in to the empty ROM and RAM slots, I came across ISA prototyping boards for a price I couldn't refuse. I'd had my eyes on them for years, always way out of my price range... and here their price-per-hole is highly competitive with regular ol' protoboards. It seemed wrong, but, lacking other protoboards, I started thinking about using the ISA board as just a regular-ol protoboard for a Z80 riser-board, where-on I could try out some of the crazy ideas I had in this TI-86ing project for things like memory paging, display refreshing, and such. But I really couldn't get over the nagging feeling about using that long-sought ISA protoboard for something completely unrelated to ISA.
...
A few days later I woke to an epiphany. A huge part of the reason I did #Improbable AVR -> 8088 substitution for PC/XT was for the sake of using and making [especially: weird] ISA cards. Here I'm planning to stick a Z80 processor, and various weird hacks, on an ISA card... I mean, wire that thing up to the edge-connector [too], dummy!
So then, I started thinking about it even more, and it occurred to me, I could quite-literally use the Z80, on that ISA card to be the main CPU in the system, by basically putting the bus in permanent DMA mode. Now we have an "Improbable Z80->8088 substitution for PC/XT"... or, really, any PC with ISA slots. Or... backplanes... or... heck, apparently there are plenty of ISA riser-cards from various weird old servers and computers... wouldn't even need to halt the main CPU for DMA, just don't plug the riser into the motherboard.
Z80 with VGA and a soundblaster, yo!
But, again, I really dig *weird* stuff, I mean VGA is great, but there must be some weird old ISA cards that no one can even figure out what they are, nevermind find drivers for, for pretty cheap, right?
So I started searching... and sure-enough I found some from what appear to be industrial systems, and others from test-equipment... And knowing a bit about what to look for, it's not too difficult to recognize whether some weird old card might be within my means to program without any documentation... Or, at the very least, have components I could be glad to scavenge.
So I found one I couldn't pass up for $9... This one has four high quality 24-bit ADCs that can sample at up to nearly 400KS/s. No small shakes, and every chip on the board is *very* well documented. But "the seller doesn't ship to P.O. boxes." So, through a bit of aggravation, I'm sure, on the seller's part, we found an arrangement that'd work... For nine measly bucks, including shipping. I felt kinda bad putting them though all that. So, well, I figured I'd see about other things they were selling, to make the extra trip to their less-preferred shipping depot worth their while... And, well, there were many other things under ten bux that I was interested in, but one really caught my eye...
A Texas Instruments "Calculator-Based Laboratory" to be interfaced to a TI-Calc... Which, as you may've gathered, I have learned a thing or two about.
This thing, too, is *very* well-documented, down to pinouts and configuration,, and even instructions for teachers to run long-term logging on field-trips off lantern batteries! And, again, every chip inside is well-documented, too. The only hidden part being whatever the microcontroller's ROM contains (and who knows, it may be dumpable).
But, before I even bothered to look up documentation, I just plopped in some batteries and turned it on... didn't even hook it up to a calculator... and... This blasted thing turns-on as a multimeter! No kidding... I had been debating investing in a couple more cheap multimeters, actually... For e.g. trying to monitor current and voltage simultaneously while charging/discharging old Li-Ions. I'd found cheapos for about $6...
For $10 and attached to a $7 Goodwill-find, I can do logging of multiple channels over hours, and graphing, and more. Heh!
This could be quite the handy piece of "lab equipment"... the sorta thing, yes, I *could* do with an AVR... and plausibly far "better" (more memory, SD-card, higher sample rate, whatnot) but, this already has the screen, keyboard, UI, analog front-end (which I'm not so great at), and more already done... and I've yet to get around to AVRing it... So... Awesome!
Heh!
Having looked up pinouts and found extensive documentation, It goes beyond all those piddly details... here's a system you can reconfigure dramatically in the palm of your hand... Have twenty different programs ready to go at your fingertips... No compy required. Plausibly combined with my TI-86 hacks (like flash-memory) it could be even better... Long logging expeditions could contain many more datapoints by transferring to the calc in realishtime, Min, Max, Average for each regular sample (say once every ten minutes)...
I've plenty of ideas how to make use of it. Logging the charge/discharge of my car battery, for instance. Determining A-h ratings of old laptop batteries. And some weirder "logging" ideas: e.g. the van gets *really hot* when the sun shines on it. Yet, the temperature at the floor feels *easily* ten degrees cooler. Opening the window, it feels ten degrees cooler than that. Opening the door, even cooler. Sometimes I'm near certain it's thirty degrees hotter in here than outside! Log That! Alongside a video, maybe. Or weird issues with the engine that can only be experienced while on the road... Can't be writing notes while accelerating... This thing does multiple channels, after all.
Anyhow, Ten Bux... I'm kinda "stoked".
Oh, and the ISA card looks pretty awesome. Only thing is an 8751 microcontroller "black box". But I think I managed to read its ROM, and it is a *very* small program that may merely be used to convert the ADCs' SPI to ISA.
I also came across another ISA card for even cheaper that I couldn't refuse, either. I'm guessing it was a power/frontpanel I/O board for an industrial backplane-computer of the sort that has the CPU on a card (kinda like I'm thinking to do with the Z80)... It's got a connector at the back for *outputting* 5V and 12V, with voltage-sense inputs on both ground and power. (but why would it send power *out* through the backpanel bracket?) Two DC-DC converters, anyhow, with their Vin, as well, at the bracket. But it also has regular ol' 7400-series, all the way to the ISA connector, for a whole bunch of other stuff, including TTL-I/O and LED drivers... So, TTL logic... figuring out how to control those I/O shouldn't be difficult, right?
Heh, who knows.... Z80 ISA computer, anyone?
-
More Z80 Hackery Goin' On...
06/20/2022 at 05:54 • 0 commentsThe poor TI-86 has gone from the number-one hacking-platform in my life for nearly a year to now doing little more than crunching numbers I should be able to do in my head...
But, I owe it (and @ziggurat29) a debt of gratitude in sealing my interest in 8bit computers, and of course Z80's in particular.
We've begun #Z80 Reverse-Engineering And Hacking Adventures anew, with what seems to be a one-off piece of lab equipment used for controlling motors in, we think, spectrum analysis.
I'll let that project's page speak for itself...
The TI-86... well... I was *so close* to actually finishing my project with it, and it would be a great tool for diagnosing some long-persistent technical troubles in my life, so I haven't exactly given up on coming back to this project... It's entirely plausible the new project will reinspire this one, after a half-year hiatus from the 8bit realm.
We shall see.
In the meantime, if you're here for Z80 goodness, maybe go see what we're doing on the other project.
-
Wait for it...
02/01/2022 at 19:55 • 0 commentsWell, I got some new-shineys! So, this project has wound-up on hold...
Briefly:
In my life"style" power is a huge concern, as is space. Thus I've been fighting (for years, really) to figure out a decent and reliable solution to the problem of having a computer at-the-ready to return to my various coding and other projects, along with organizing photos, etc.
("Briefly" never seems to be so brief when I start writing)
That's a huge reason I took on *this* project, because the only thing I need a regular-ol' computer for it is making backups and occasional serial debugging. All the actual coding has been via the TI-86 keyboard, and all the assembling has been done on the TI-86, too. (!) Which has given me a good excuse to learn and practice assembly, despite my preferring the portability of C.
But, it is a much slower process than I expected, and I do have many other projects which need gcc and such. Nevermind the not-so-rare occasion I could *quickly* throw-together an AVR based circuit for a random need here and there.
What was I wanting that for recently? Oh, the *far faster* comparator in an AVR than the linear ICs I've got would be handy for my boost circuit for driving LED "filament" strips for a TI-86 backlight. Oh, and a current-monitor to keep my USB battery-packs powered-up regardless of low-current... Both of which can likely be done with a 555, but it really isn't my realm, so instead of being a quick day/side-project, it turns into a multi-day project-derailing new project of its own. Again, an excuse to learn new techniques, but also not particularly ideal functionally, as these things are *really* slow compared to a 20MHz AVR... meaning larger inductors/components and higher currents, among other things.
OTOH, TBH, I don't really know what I'm going-for anymore... the learning-experience is "fun" in a way. Maybe "the fun?" But, it also feels like at this rate I'm never going to get to the things that motivate me. And I've *tons* of those just waiting to be tackled... Hobbled by so many limitations in this still "new" to me life"style" (half a decade, now), I feel like nearly all the things I am (or was) good at take *significantly* longer than before, if not just darn-near impossible. Imagine a carpenter without a table-saw!
So, for some semblance of the life I knew for so long, I keep striving to find solutions to these hurdles that didn't exist before...
One of those was purchasing a butane soldering iron. A far cry from the industrial-grade iron I invested in back in highschool. Merely taking it out of the box and finding workspace is a chore compared to decades of just flipping a switch. Nevermind waiting for it to heat up, then having to do-so again after refilling, quite often. BUT: it's a significant improvement over the past several years!
So, the same goes for computing... I tried a couple laptops, but they drew so much power that it was barely suitable for an hour's use. And, frankly, they take up a lot of space in this environment when set-up. A buddy I met here thoughtfully hooked me up with an Atom-based system a couple years back which I was able to finnagle into a spacially-suitable form... which worked great for a year or so. But in trying to increase its ruggedness, I managed to damage the board. Heh. Out of desperation to keep project-momentum I threw a Pi Zero I had planned for another project in its place... And that has been my main system, aside from my phone, ever since. Frankly, *excruciating* to even do a quick web-search on. But, functional-enough for most my needs. My buddy since thoughtfully hooked me up with several assorted atom-based boards to potentially plop back into the system as a brain-transplant... But, therein lies another conundrum... I've managed to fry (and replace) various components of the Pi-based system since the initial setup. Apparently proper grounding is a huge concern in an All-DC environment. First to go was the HDMI port. Thankfully I had a parallel-interfaced display from an old DVD player, and thankfully the rest of the Pi was OK, so I wired it up to the Pi's DPI. In the meantime I figured the portable HDMI display no longer necessary, so passed it along. I bought another PiZero for the original project plan... which apparently was smart to have around, since several months later the first became quite flakey, powering down randomly. Plop-in replacement was quite nice, taking only a few hours to solder-up, and again barely hindering project-momentum.
I dunno how I've had such bad luck, though, with reliability of such things these past years. I built computers as a young teenager that were passed-down for over a decade!
(Oh yeah, my first laptop in this environment fried its CPU! Sony!)
So, now, it seems the only way to have a reliable system is to have *numerous* identical-parts systems ready to go at the drop of a hat. Sheesh.
...
A few months ago I caught wind that someone had come across a goldmine of mostly-intact Atom-based tablets headed for the dump... All nearly identical and functional... And so many that he was literally giving them away. Score!
Seriously, this could be The Solution. They arrived recently, and I've been working toward replacing the PiZero based system.
I can't thank Mike enough for the incredible amount of work he put into keeping these out of eWaste, and passing them along to folk like Hackadayers who aren't deterred by a missing battery or back-cover.
...
That said, I've really been struggling to power these crazy things reliably. The latest is two pretty new and recently stress-tested 18650 cells totalling 90% of the original 6Ah... Soldered directly, with no removable interconnects, via comparatively huge wires... Looking at the chintzy battery connector these came with, and the tiny wires, it's really a wonder these things ever worked... nevermind if someone connected, say, a phone to the USB port, drawing an additional half an amp. These things have been powering-down with no warning on countless occasions and seemingly rather unpredictably, even when externally-powered. And charging is another thing entirely.
Word has it, they're reliable with quality high-current power supplies and beefy wires, but of course that's not what they were designed to be packaged with, so it really makes me wonder.
Though, I haven't got /brand new/ batteries to try, maybe they'd be more reliable then. Regardless, they wouldn't be brand-new after a month's use, so... back to wondering...
Maybe that's why so many of these were dump-bound, with the batteries removed.
If I am to replace my PiZero system with one of these, it really is a relief I have so many for drop-in replacements! Heh. But, I won't be making that transition until I can get it reliable enough in my environment just to run reliability tests. Heh!
I've no doubt they can be quite useful in the right environment... Some folk have mentioned clusters with heavy bus-bars for power and heavy-duty power supplies. Many have removed the screens altogether.
Since I plan to use USB alot (programming dongles, serial debugging, keyboard/mouse...), I'm working on a separate battery system to power a hub which will be mounted "internally". Similarly, I plan to use a hard drive, which will have another such (separate) battery pack.
My experience with USB battery packs is that they A) only maintain power if at least 100mA is drawn B) cannot power a device while also connected to another power source for charging C) there was a C... I'm forgetting. So, it's not just merely a matter of powering the hub and drive off separate stock usb battery-packs. Oh, C... Can't be turned off without unplugging the load.
First experiment was ripping out the charger/output circuit from two packs and attaching both to one set of cells for simultaneous charge/discharge. It seems to work OK, but the charger does get confused about what the charge level is. And the second (for output) even more-so. Unless the charger is enabled on its board, it never increases the "bars." And if it's allowed to discharge low-enough to shut-down, it seems it remains in that shut-down "protection" state even if the cells are fully charged thereafter by the other circuit. Hah! So, it's a bit wonkey, but I think I can work with it... Maybe I'll use some glue-logic on the LEDs to light up an obnoxious warning when the outputter reaches 1 dot.
But, now, what if the hub draws less than 100mA when unused, or the Hard Drive does when spun down? Now I need a circuit that monitors the current draw and/or pulses a 100mA load every few seconds. (and, btw, needs to power it up immediately when the system powers-up). Or, since the packs have been opened, those pulses could be applied to shorting the power-button, instead... Regardless, yet another circuit.
Now, what when the system is powered-down, but say something is still plugged into the hub, or the hard drive still draws 100mA when powered-down... Or, actually, neither of those matter because when the power packs are "off", it just means the 5V boost converter is disabled, but the 3.7V from the battery is still at the output... So, I don't want to be driving my hard drive at 3.7V... ever... and certainly not for days while packed-away powered-down. So, now, P-Type MOSFETS between the positive output and the hub/drive. Another bodge-circuit. Heh! And, NO! Do NOT think about using the NFETS on the ground "output" of the boost-circuit... Nor putting another in series with it because: Ground will go through the USB cable, instead.
OK. Now... I think this should be an OK-enough "UPS" for the drive and hub, allowing the entire system to run portably off batteries AND while connected to a "charger" (though, in all three cases, the tablet, drive, and hub) it's entirely likely the chargers /won't/ supply as much current as is being drawn, and any/all of these battery packs may discharge (at different rates!) while in-use /and/ "charging". Heh! So, now, the LED "bars" would be quite handy, but of course they only go down on the circuit outputting current and up on the circuit charging.
WEEE!
Somewhere in there is the idea of using diodes (or FETS) to steer 5V directly from the charger input to the load when plugged-in, thus the batteries are *only* charging. But that introduces a whole slew of other issues... E.G. now my 5V supply has to handle double the current. And the tablet itself isn't capable of running this way... Interestingly, it has been known to run reliably on 5V at the battery terminals *if* the 5V supply is capable of the current demands, including potentially huge spikes. Hmmm. But that would mean charging the battery from a separate charger... Oh, and worse, right...
When disconnecting the USB packs from the charging source, they take time to power-up... about 1/4th of a second, if I recall. So, upon unplugging the external supply we need a huge capacitor for the load and circuitry to immediately detect power input removal and begin the powerup sequence, but not allow that capacitor to drain into the battery before the booster kicks in. AND, not drop much voltage, either, so rather'n diodes, we're talking PFETS again and detection circuits. Ugh.
Shouldn't this be a common-enough use-case to almost be default?
And, upon rereading it occurs to me that 1/4 second power-up time might also be an issue when powering up the entire system... All those things would be on USB, so technically don't have to be powered up to boot, but I'd intended to boot off the drive... so need to think about this a little more. Why /not/ use the eMMC to boot? 32GB should be enough for linux and most my programs, and would probably be faster than USB... I guess part of the idea was the reliance on "plop-in" brain transplants, if that remains a problem. And not sure how my backup-system, if ever needed, would *restore* to a new machine... Would have to be bootable! Oh yeah, and I *really* don't like the idea of swap space on FLASH drives.
The idea, again, occurs that the USB devices could be initially powered through a diode from the main system battery during that 1/4 second, but I don't think its boost circuits are suited for an additional potentially 4A load, even briefly.
I'm probably overthinking this, 1/4 second is shorter than "Press Esc to enter BIOS Setup".
...
However, now I am, again, pondering diode/FET-steering when plugged-in for charging. Heh. Why not? Big 12V-5V converter(s!) I guess would be the main reason. Or maybe two 2A converters per battery-pack/load pair is smarter... Hmmm... Would certainly make for faster charging... Oh, right, /except/ for the tablet itself. That can run off 5V at the battery terminals, but definitely draws more than 2A at times... I dunno, maybe working a high current USB pack into there isn't a bad idea. The charge/discharge indication is pretty wonky anyhow, LEDs are nice.
...Anyhow, I suppose it should be pretty self-explanatory that the TI-86 project has been put on hold, which actually isn't so great, because that project is a tool to help fix something rather important to my life"style". Heh. My brain does not switch between projects easily... Once the momentum builds up...
...
LOL That was February First, it's now May Ninth.
Progress has been minimal despite COUNTLESS attempts.
The main problems, I guess, are the facts that: Diodes aren't an option due to forward-voltage drops (0.4V at best with a Schottkey), and due to the fact that mosfets have a friggin' body-diode. (How could this have only come to my attention recently?!).
I've come up with a circuit containing a Series of Four P-Channel Fets. Mine have an RDS-On of 0.05ohms, which sounds like nothing until you consider four in series and a 2A load... Now my 5V hard drive will get 4.6V at-best. Numbers like these do not appeal to me!
So I've literally spent Months trying to reduce the count of series-fets. I think I was able to get it down to three, at one point. Still, 4.7V doesn't seem great, and who knows if my batteries/supplies actually hold to 5V at a 2A load.
Anyhow, it's a long story involving the need to cut the load off completely from the battery, then merging the battery and "line power" supplies, then charge a huge capacitor (at a limit of 2A!), then power-up the drive after the capacitor is fully charged. All the while preventing backflow from one supply to the other, or even from the capacitor to the supply. (even 0.01V difference would result in AMPS!). This is not at all my realm, but I'm sorta learning.
...
I splurged on a surplus doodad which seems to have completely escaped documentation on the web. It has RS-232 and GPIB, which I'm near-certain must mean there's a Z80-era CPU involved, which have piqued my interest lately... Fifteen measly bucks, which is less than I'd've had to invest in an order of newer lower RDS-On mosfets... And they just happened to have those, as well, at a great price. So, four series P-Channel FETs may well be in my future... 0.017ohms each, as I recall. All Four would roughly amount to one or two of the ones I was planning to use. 4.8V doesn't sound *so* bad.
...
But, shoot, where was this all headed?
it's still a ton of circuitry... A current-limiter, two "ideal diode" controllers, and more... And MOSTLY analog (OP-Amps) which usually bite me in the a** even after simulations. I *think* I might've figured out how to avoid my arch-nemesis Common-Mode-Voltage, this time, but I won't know until I build it.
And, of course, none of this has anything to do with the original project, here... And, maybe worse, if I get those tablets running and rugged, could basically completely nullify what I'd been trying to accomplish with the TI-86... Logging and Graphing, in color, in MBs, heh. That'd be /really/ useful to the original goal... which was to diagnose my engine troubles. Yahknow, what... a year or more ago.
So... Will I ever get back to the TI-86ery? Heh. Maybe this surplus doodad's internals will reinspire that. I dunno. I've been pretty intrigued with that era's electronics since I got into this stuff in my preteens, so it's unlikely I'm quitting... but it may be a long wait.
-
More Wild Speculation...
01/22/2022 at 21:07 • 0 commentsLet's say my huge code is correct, that I didn't mis-count T-States, etc...
If the huge code works *without* counting M1-waits, but does *not* work when counting them, then most-likely that means the T6A43 does *not* have M1-waits. Right?
But, again, assuming my code and T-State counting is correct, then I should be getting the same results in measuring the T-States in a specific time duration via two different methods, which I don't.
So, now, Here's an odd thing... Regardless of whether I count M1-waits, my two time-measurement methods are off by about 2%. However, what *does* change, depending on if I count the plausible M1-wait or don't, is which timer-function reports having counted more T-States during the same time duration.
So, In the last log I did a lot of wild speculation...
And, here I do some possibly even wilder...
What if there is a half-cycle M1-wait?
This doesn't work with the standard Z-80, since the /Wait input is only sampled on the falling-edge of the clock, *and*, even if it sampled on the next rising-edge (during the previously-requested wait), then all the clock levels/edges thereafter would be swapped.
But... Why not?
As @ziggurat29 pointed out in a comment, the T6A43 ASIC (not VLSI, as I always mix-up... AS != Average Scale, AS=Application Specific).... The T6A43 ASIC is, exactly that, Application-Specific, AND, Far Newer than the original Z80...
So, what could that imply?
Well, first, 6MHz, as most claim the clock frequency to be, was well within the speeds of the era this was designed.
Second, it seems to have been designed for an RC clock... I dunno off-hand how it's implemented, but an easy-enough way would be simply to discharge the capacitor through a transistor, then allow it to recharge through a pull-up resistor, until it reaches some threshold voltage, then discharge it again. Creating a sawtooth wave... which doesn't really do too nicely for a digital circuit like the Z80 which does things on both edges of the clock. So, the simple solution would be to run the sawtooth at Twice the frequency, then use a Toggle-Flip-Flop to divide that in half for a nice 50% square wave.
Now... If one happens to be designing an ASIC like this in some newish era where memories are *much* faster than the original Z80 was designed-for, BUT, there still remain vast quantities of those older slower memories, AND, in that same era tradeoffs were also being made for speed vs low-power... One *Might* consider speeding up the Z80-ASIC a bit for later end-product production-runs, but ALSO leave the option to use slower memories in present runs.
OK... So we come to my weird thought... in a bit... So, maybe the T6A43 is really quite capable of much higher clock frequencies than 6MHz... Then maybe even those newer-faster memories would need wait states...
Alright. Now, unlike a real Z80, we've got control of the Discharge transistor for the RC "oscillator"...
When a /Wait is detected, we could simply discharge that capacitor a little bit early, either at a lower threshold voltage, or, frankly, even *immediately* when that clock-edge is detected alongside the low-active wait. until it is no longer. And thereafter our clock-periods return to normal. Now we can control our wait-state durations externally... Fractions of a typical clock cycle or multitudes.
This, I think, should be a pretty simple thing to do, when you've got gate-level access to the z80-internals. And even those *extremely* fast clock-cycles merely sampling the /wait shouldn't be a problem, since I'm guessing the entire CPU basically halts, holding its state, through wait-cycles.
The next thought, for me anyhow, is whether similar could be done with a real Z80... And, I think I've come up with external circuitry that could at least make for /half/ wait-states. The key, in this case, is whether the Z80 would freak-out if suddenly one clock pulse was missing or shifted slightly...? Why would it? There's no PLL generating multiples of the clock frequency in there, right? Presumably it does most everything based on its two clock edges, and anything it does inbetween is due to propagation-delays.
And, if it's true that the Wait states halt everything in the CPU short of the circuitry detecting when to return to normal, it would seem rather likely the clock signal input itself is basically *removed* from all except that circuitry during waits... So, seems rather likely the clock signal could actually run *much* faster during a wait... say double (since the wait-detection only samples on the falling edge). And that clock-doubling can be done by adding a T-FF and some glue logic. Much easier if you have access to the internal gates, but not particularly difficult if you don't.
Half an M1 wait-state would bring my timing measurements to nearly identical.
It may also explain why my system works without counting M1-waits, but *doesn't* if I do... Because, again, the error may be the same between my two measurement schemes, but it's *swapped*... So, the half-M1-wait measurement-error in my system neglecting M1-waits isn't too bad, but increases quite a bit when using Full M1 waits, due to the facts: the measurement loops are *tiny*, so M1 error *barely* affects their results, while the actual loops which rely on those measurements are comparatively *huge*, tallying up a LOT of additional T-States through a lot of small instructions. (5 additional T-States in 35 is quite a bit less error than 1 in 4).
I dunno, it's a lot of speculation that, really, I don't /need/ to do since it does function, if for the wrong reasons. It'd be nice to hook up #OMNI 4 - a Kaypro 2x Logic Analyzer and get some real answers, heck, that thing was practically designed for this! Alas, that'll have to wait...
...
Of course, I couldn't.
My Omni4 has only one (of two) pods... which means I can only sample 8 bits, along with a clock and a trigger. Frankly, I'm very curious about the clock, itself... Does it stay relatively steady throughout various instructions? Well, I could be wrong, but I'm guessing the "clock" input is used to latch in data, as opposed to being sampled (multiple times per cycle)... So, 8 bits of data is a bit limiting in a logic analyzer. I don't think I'll be able to use its z80 instruction decoding.
OTOH, I don't *have* to use that software-decoding... and the OMNI4 can allegedly sample at 20MS/s... So, if I'm thoughtful about it, I'm sure I could determine a few things with what I've got.... and, maybe it's good I only have the one 8-bit pod, 'cause soldering 24 "pigtails" to probe seems a bit ridiculous, if not exhausting.
It may happen... If I plan it right, it's a matter of soldering pigtails, doing a quick run, maybe taking some photos, then visual post-processing.
-
M1 wait-state? Revisited
01/17/2022 at 20:53 • 3 commentsI've several past logs regarding the possibility the T6A43 Z80-alike makes use of a wait-state on M1 machine cycles.
These are my latest findings:
First, the setup:
I have a 41.667Kb/s serial signal, pulse-width-modulated (a 1 is a 16us high, 8us low, a zero is 8us high, 16us low) and a 4800bps UART serial signal to compare to.
41.6K is too fast to process in realtime, so I first take 1024 samples then post-process. A packet usually consists of 49 pwm-bits, and I generally measure around 272 samples containing a frame. I use the INIR instruction to grab 256 samples at a time, and pad with a nop between INIRs. Thus, each sample should be 21T-States (unless there are added wait states).
Yes, I disable LCD DMA and interrupts.
272samples/49pbits×21T/sample×41667pbits/sec gives 4.857Million T-States per second.
Then, in the same program I "autobaud" by measuring the number of T-States during a "?" received by the UART at 4800b/s. The use of "?" for autobaud makes it easy to see a distinct change between the start bit and the first data bit, and the last data-bit and the stop bit.
I measure the number of loops between detection of the start of the first bit and detection of the end of the last bit. Each loop is 35T-States long, assuming no wait-states. Though, the loop looking for the first bit is 29T-States.
The counting loops look like:
inc hl ; 6T
in a,(7) ;11T
and b ; (rxMask) 4T
cp d ; (rxOne) 4T
jp z, loop ;10T
If M1 waits were implemented everywhere, this loop would be 40T-States instead of 35, and the INIRs would be 23T instead of 21.
The autobaud measurement determines 993T/bit at 4800b/s, which amounts to 4.766Million T-States per second vs. the other measurement's 4.857. That's an error of about 2% which is enough to begin being concerned about UART timing.
So, I started looking into potential error sources and whether they could account for the difference. First and foremost, if an M1 wait-state went unaccounted-for those numbers wouldn't get *closer*, they'd in fact veer even further apart. 5.45MHz vs 5.32MHz, 102.4%, vs 4.77 vs 4.86, 101.8%. A minor difference, I suppose... I could've sworn it was further off than that.
So then I tried to account for the error elsewhere. E.G. what if the edge of a UART bit occurred immediately after sampling, then there'd be nearly 35T of error. And if the edge of the last bit occurred immediately before sampling, then there could be an additional nearly 35T of error.
But... at 993T/bit, or 7945T/8-bit frame, that measurement error is nowhere near enough to account for 2%.
This is important, again, to my project because ultimately I won't have autobaud as an option and will have to generate my UART timing based on the 41.6Khz signal. I looked at it with a scope and measured darn-near exactly 41667Hz. So, it's plausible my 4800bps UART connected to my computer (via USB) is off by some UART-Acceptable percentage. And/Or it's possible M1-Waits are a thing...
But I ran some numbers and found another plausibly-reasonable explanation...
Note, I went through all this because: If I autobaud accounting for M1-waits, and also account for M1-waits in my UART code, it sends/receives garbage.
The other plausible explanation I came up with for the 2% error between the 41.6k signal and the 4.8k signal is that I/O may have wait-states. If there is no M1 wait-state, but there is one wait-state for port reads, then the numbers drop from 2% error to 1%. If, plausibly, INIR has two wait-states (why?) then the measurements from the two sources align almost perfectly at
... DAGNABBIT!
I did these calcs yesterday, and they did add-up. Why The Heck aren't they now?!
I thumb-typed this whole thing for no reason?!
...
GAAAAHHHHH!!!
This Is Really Frustrating.
I spent *weeks* making all the code switchable between M1-waits and no M1-waits, had to recount every friggin T-State in every friggin function *several* times, because at first I was *certain* M1-waits were the culprit, despite the fact autobaud and my UART code worked together without accounting for it. So, at first, I just deleted all the T-State counts that *didn't* include M1-WAITS... Then recalculated everything based on M1-waits, then it stopped working. So then I spent several days /again/ pouring over all that code, again, to put Non-M1 counts and calcs *back*... Then switching between them was too much a pain, so I rewrote the code with .equs that allowed for quickly switching... And, STILL, it only worked with *not* accounting for M1-waits... I mean, I've looked that code over *Numerous* times.
Last night I *Finally* came up with an explanation... Got that error between autobaud and the 41.6k signal down to a fraction of a percent by a reasonable explanation (a wait-state on I/O transactions)... And now those numbers don't add up.
Heh.
Problem is: 2% error isn't a whole lot, but it can be additive in the case of UART bitbanging. At the end of 10 bits, it could be off by half a bit or more, which could be too much. But, more likely problematic is that that 2% will be added to the error in my measurements and in my bitbanging delays... Which I designed to be as error-free as possible, expecting maybe 2% worst-case. They might cancel out, or they might sum-up, now to 4%. Heh. I could just try it, as is, forgetting the error, and it may or may not work. it may work most of the time, but fail seemingly randomly.
THIS part *should* be pretty easy to "get right"... the pwm and autobaud sampling loops are *tiny* in comparison to the bitbanging loops. Surely I can account for a difference when dealing with 21T and 35T loops on the same source.
Maybe I need to run the sampling/post-processing on the same autobaud source and see how they align. SHEESH. This Just Keeps Dragging Out!
...
oh, but worse... Because the UART code does NOT work when counting M1-WAITS... Because, even though the error is about the same for the two methods, around 2%, regardless of M1... The error is *reversed*. In one case pwm-sampling measures the higher clock frequency, in the other case autobaud does. What The Heck.
Same source... I need to measure the same source. *Sigh*
...
Hours later, autobaud now runs both ways, from the same source ('?' at 4800bps); sample-first, then count samples, and count loops between highs and lows in realtime.
Dang-near /exact/ same results.
4.82-4.84 million T-States when sampling, 4.74-4.76 when watching for edges in realtime.
I've checked the realtime edge-detection code several times since designing it, and again, now. It's a tiny bit confusing because the loops *start* with the increment, and exit after sampling. So, technically, if you think of each loop as a single unit, then the counting is off by one... so it's a bit confusing and could lead to an extra or missing count if not handled right... I can't count how many times (and ways) I've drawn a timing diagram to make sure... But, even still... even *Numerous* missing loop-counts don't account for 100kHz difference.
Is it plausible the RC oscillator varies /that/ much, consistently, (and so quickly!) based on the types of instructions executing?! Maybe due to voltage sagging with power-usage or something?!
This sh** be crazy!
...
So, if today's math is right, there's no confirmation either way regarding M1-waits. It's about the same percentage-error either way (just swapped).
And if today's experiment is right, that the clock frequency may vary somewhat dramatically depending on what instructions are executing, then even my /original/ autobaud/UART results (that the UART code produces/receives garbage when accounting for M1 waits) may be non-indicative, as well....
Again, the difference between the sampling and edge-detection methods is 21-23T states vs 35-40T... just a handful of instructions. But the UART bitbanging code is *huge* in comparison... About 200T-States to handle each bit, calculate the remaining delay, and then the delay loop itself. So, being mostly small instructions, an additional T-State on each results in a much greater difference in the end.
If this thing *does* use M1-waits, my accounting for them in the code may very well be overrun by the newly-discovered plausibility of inter-instruction clock-variance!
Despite ALL those weeks of careful calculations, it may've been just LUCK that my two systems worked together based on a bunk assumption, and *don't* based on the reality of the system!
GGGGGAAAAAAAAHHHHHHHH!
-
The "Blacklink" is handy!
01/07/2022 at 00:40 • 0 commentsI keep finding uses for it in ways never intended. There's a previous log where I talked about it, some, and drew the schematic...
I've used it in /many/ different ways, now... Note that, as I recall, the comparator runs down to 2V and can accept inputs up to 18V or so even when the supply is lower.
The "bias" (more like "threshold") voltage is 1.65V, which is a pretty decent threshold for many different signals, including "today's RS-232", TTL, 3.6V USB-Serial, and even 12V signals in a car...
My USB-3.6V serial converter has a 3.3V zener at its Rx input, so I considered just connecting the calculator's link port to Tx and Rx, directly. BUT, actually, the calculator could feed up to 6V back into the /Tx/ line, which I don't think is a good idea. So, I just threw the "blacklink" between, for good measure. Its DB-9-side input is not pulled-up, so no feeding 6V into the 3.6V output on my USB-Serial Converter. The pull-up at the graphlink's output is pulled to the voltage of the DB-9-side's largest voltage, which is 3.6V from Tx, so the zener's really not necessary.
Anyhow, I'm not really wording well right now, but here's the current use-case, very different:
PWM is (I think) open-collector to ground, pulled up to 12V. I need the calc (circuits on the right) to read that, not write. The graphlink circuitry inbetween not only converts that to TI-link's levels, but also supplies 12V to the graphlink's circuitry through the diode at the input. Since it does this, I'll probably wire up 12V directly to the graphlink's power capacitor, just in case that pull-up and the heavy data flow allows that voltage to sag.
But now there's 12V in the graphlink... what about connecting to my 3.6V-UART signals? (BTW, did you notice the blacklink /also/ adapts my 1-wire bidirectional UART (on the calculator's red wire) to Tx and Rx for my 3.6V UART? Handy!)
Tx is simple-enough. There's no pull-up on the DB-9-side inputs. Threshold voltage is 1.6V. Great!
Rx, well, I already have the 3.3V zener at its input, and since the blacklink doesn't /drive/ during high outputs, instead pulling up with a resistor (yes to 12V, weakly) the zener shouldn't have to sink much current to keep a high input at a 3.6V-logic-safe level.
That's pretty much it! Now my calculator can interface its bitbanged 1-Wire bidir UART with a 3.6V 2-wire Tx/Rx UART AND read a 12V "clock" signal from my car. And all i had to do was reroute a few pins from the graphlink's DB-9.
(OK, and make sure there's a zener on Rx, and I soldered in some wires to the blacklink's power capacitor a while back).
....
Trying to parse this from TI's datasheet of the LM339 comparator used in the blacklink:
"The upper end of the common-mode voltage range is VCC+ – 1.5 V; however, one input can exceed VCC, and the comparator will provide a proper output state as long as the other input remains in the common-mode range. Either or both inputs can go to 30 V without damage."
...
This note seems in conflict with other specifications, especially "Recommended". OTOH, without taking this note into account, the blacklink's circuit is not within the Recommended specs. Because: It draws its power /from/ the input... through a diode. So the input voltage might be say 0.6V higher than VCC. The above quote seems to be saying that's OK. The recommended parameters don't.
The alternative is to consider the second diode at the comparators' inputs. This is reverse-biased to ground. Initial guess was to protect the comparator input from /negative/ input voltages, which would likely be present on an RS-232 signal. Bringing a negative input to, say, -0.6V. This is out of range, too. -0.3 is the LM339's spec... So, maybe it's shotkey. But, then, unless it's zener, the input still exceeds VCC. Meaning the above note is important to its design.
Currently, this is especially relevant to my hacked-use of the blacklink.
Usually its inputs are connected to RS-232 signals which actually have high/low /drivers/ rather than open-collectors with a pull-up resistor. So, my 12V signal will try to power the circuit, through I think a 250K resistor... Charging this thing's capacitors will probably hold that signal low or indeterminate for some time. Not a great idea. I guess that's the answer. I really should power this thing externally.
The other input is connected to my 3.6V driven signal, which mostly sits idling high... so the 339 would be reliably powered to 3.6V minus a diode drop. And, I think, the above note says the circuit itself should be fine with that, even with a 12V signal at the other input. But, since the other input also has that diode to VCC, the 12V signal will try to /increase/ VCC to close to 12V, at the expense of dragging that input signal down with it... Which might interfere with whatever communication goes on there (even though I don't intend on reading it).
So, it seems, I need to actually power the blacklink's VCC with 12V. Again, no biggy, electrically... Its design won't put 12V on my 3.6V signals, which was the original concern. (It wil pull up to 5V, but my input has a zener regulator). So, I guess it's kinda funny that the concern isn't about overdriving low-voltage inputs, neither at my 3.6V circuitry nor at the possibly under-voltaged comparators (which apparently could handle it, even if it was powered by 3.6V?!), but instead the concern is overloading a high-voltage output.
Yep. I should power it with 12V.
Good thing I soldered leads to its capacitors!
...
NO! I've gone over this before, sheesh... Am mixing up ghe Link-side with the DB-9 side of the graphlink. The DB-9 side outputs are pulled up to VCC (~12V, in this case). That'd be fed into my 3.6V input, if not for the zener and resistor at its input. I think it should be OK, but it may sink a bit of current. I stupidly put that resistor in heatshrink, so dunno its value. my plan, originally, was interfacing it with 5V logic, so 220-2.2k ohms mighta been the choice. Probably lower than higher since I probably tried to account for high baudrates. But, the pull-up in the blacklink should be probably 10k or more to match.... dagnabbit, NO! Wrong side again. DB-9 side. Still, OK... RS-232 can be +-15ish V... so that pull-up must be high-ish valued, otherwise it'd drop mAs whenever the output was low... So, whatever value it *is* should drop even less current when regulated to 3.3V rather than tied to ground... O.K. whew.
-
Where Am I?
01/06/2022 at 04:55 • 0 commentsSo, in a recent past-log I finally explained what it is I plan to do with this calc-hackery...
And that had been kinda side-lined due to other/new issues with the very thing /this/ thing was intended to diagnose. heh.
Anyhow, Thank Goodness, it seems those have subsided, so I can return to this to help diagnose that's long-term ailments.
...
I'm interfacing with a 1-wire bidirectional UART... It works on a request/response basis. And, frankly, I don't really have a whole lot of /reliable/ information to go on about the structure of a request. So, until I get that right-enough, the responder might very well stay completely silent.
This, combined with the fact the z80 CPU is clocked by a somewhat variable RC-clock, makes for a bit of an issue when it comes to bitbanging a UART to communicate with it... If the responder sent out a message every so often, I could determine its bit-duration (with respect to the CPU frequency, NOT WRT seconds!) with some sort of autobaud system. But, since it only speaks when spoken to (correctly!), I can't autobaud from it.
Thankfully there are /two/ serial communication busses in this system. The other, which I will otherwise not interact with, has chitter-chatter going on quite regularly. So, I can autobaud off that!
Sorta. It communicates at a MUCH higher baudrate, so fast, in fact, that the calculator CPU can /barely/ read the port fast enough to catch every bit, and certainly too fast and too regularly for the calculator to actually process the data.
But, it /can/, just barely, catch every bit. And the packets are also rather long, which is helpful because then I can get a good sense of the CPU's clock speed with respect to that baudrate... 41.6K. It's also quite handy that protocol is "PWM" rather than a typical UART, because that means Every Bit has both a high and a low, and thus an inherent bit-clock.
So, if I create the fastest sampling loop possible on the z80, I can sample just fast enough to see every high and low. Then I can divide the number of samples by the number of bits, and a little bit of dimensional-analysis math to determine the actual CPU speed... in actual Hertz.
From there, I think my references are pretty consistent that my UART needs to communicate at 10.4Kbps. So, now Ican figure out how many CPU clock cycles should occur between each UART bit.
YAY!
Since I'm going into this rather blindly, I've been developing quite a few tools, which are unnecessary in the final project, in order to test things as I go with an actual computer rather than with the most-likely silent end-goal device.
That means e.g. in order to develop the UART bitbanging code I needed to interface it with RS-232 at a normal baudrate ("10.4 Good Buddy!" just ain't normal). And detecting the CPU frequency, in that case, had to come from the computer, too, rather than my 41.6Kbps serial bus. So, that meant developing a real "autobaud" function which will never be used in the final system. heh!
Similarly, Bitbanging the receiver is very different than bitbanging the transmitter... So, those two systems are different "libraries" altogether... But they have to work together. Since RS-232 is /not/ one-wire, I started with the receiver and transmitter on separate pins on the calculator's link port. But, later they'll be on the same pin. Thus I continue to develop "iPort7," "iUAR," and "iUAT" such that switching pins is merely a matter of changing an ".equ."
But, that's further complicated by the fact that Port7 is /not/ Read-Modify-Writeable! So, every time one pin on the port is written or reconfigured (input, output, pulled-up, driven high, pulled low, Hi-Z, ...) the /other/ pin must be accounted-for, too. iPort7 now makes that quite a bit easier, such that e.g. I can work on developing iUAT without knowing or caring what the other pin is used for.
Also making that easier is the fact that these processes pretty much /can't/ be multitasked. There's really not much CPU time left once you shift bits and add a variable time delay... So, kinda inherently one knows that the unused pin shouldn't change in configuration during a byte transfer.
This is a bit of a backwards step for me, I'm used to trying to multitask in such projects. A 20MHz AVR is literally on the order of 100 times faster than a 6MHz z80! That's something that's really taken quite a bit to wrap my head around... I really thought it'd be more on the order of 10x. So, e.g. new Arduino users might make an LED blink by toggling its pin then delaying for a second, then repeating. And as they progress they might do similar in blinking that LED much faster for, say, an IR remote control. Using microsecond delays. But, that AVR could /easily/ be doing many other things during those microsecond delays if it was coded differently. So I've long since developed a round-robin system where nearly all my libraries do a small task then allow another to do its small task. E.G. "if it's time, toggle the LED".
That system also relies heavily on a constantly-running microsecond-ish timer... which the z80 doesn't provide. But, even if it did, frankly, I don't think it would be fast enough to do any other, even /tiny/, tasks during a delay of ~0.05ms (for 9600bps) between bits (after calculations, shifts, port-writing, etc.) In fact, I wonder if it could even handle a few pushes/pops (nevermind calls/rets) in that time.
Hah! Seriously, this is a very strange concept to me... If you want to toggle a pin ten times a millisecond, then put in ten 0.1ms delays! I dunno, maybe I'm the only one who sees this as weirdly foreign.
Anyhow, so that means we have to do everything step-wise...
First, sample the "white wire" as fast as you can, storing raw samples straight to RAM... that's 1024 BYTES for 1024 BITS of useful data, which might've been far less acheivable in the original z80 era, but now we've got bank switching and more (but not /far/ more) RAM.
Second, walk through every sample, counting high-low transitions... oh, but first, look for the start of a serial frame, because the bus /does/ idle briefly sometimes, and that'd screw up timing measurements. Stop when you see the end of a frame. Keep track of how many samples were within that frame, and how many bits.
Third, calculate the CPU frequency. Then the number of T-States that should occur between each bit at 10400bps.
Oh, but now it gets really complicated, because we're ready to transmit a request over the "red wire" UART...
So, how many T-States (CPU clocks) does it take to set up a bit; shifting it into the Carry register, then jumping as-necessary to write either a one or a zero to the red wire, but not affecting the configuration of the white wire? And how many nops must be placed, where, to make sure that both those jump branches take the same number of T-States? And, wait, nop is 4T-States, but I need 5! (BTW, ret z is 5 T-States when Z is not true, so there's your very weird 5T-State "nop"). OK, we've used X T-States, but we need Y between bits... But Y is variable depending on the temperature, or battery level, etc.
So I can't just delay 1/10400th of a second, for MANY reasons: Setting up that pin toggling takes a surprisingly huge fraction of that... that must be subtracted. And, of course, if it's cold out 1/10400th of a second might be 400CPU clocks, but 450 once the cabin's heated up.
So now we need a pretty sophisticated delay function that needs to know how many T-States were used externally, Knows how many (varying) T-States it /should/ delay, calculates how many are remaining, subtracts the number of T-States /it/ used in those calculations, then, finally, delays.
By that time, really, there's less than 100T-States to delay. And the delay loop, itself, takes around twenty. And, you may've noticed, 20 T-States of error in 400, ten times (for a serial frame with a start and stop bit), is 200 T-States of error, (half a bit-duration!) by the end of the serial frame. That /might/ work with some UART receivers, but is far beyond reliable.
So, now, the delay function has to track its error and make up for the last error the next time(s) it's called. This is OKish, I think, because most UART receivers I've encountered sample each bit near the middle, and +- 20/400ths is nowhere near the middle of a bit. So, if it goes over by 20T-States in the first bit, it'll be 20 fewer in the next. (hmmm, is that bit then 40 short?). Of course, if it goes over by 5 each time, then it'll take 4 bits/delays to make up for it. Heh! But, I'm pretty certain that inter-bit "jitter" is acceptable.... FAR better than 200T of additive error.
The weird thing is how all these numbers seem to /just/ fit.... After all those calculations, and the tightest delay loop I could come up with, it really only delays maybe four or five loops. Any fewer and I dunno if it'd be accurate-enough to work with both 10400 and 9600 (for testing) at various temps or batery charges.
Similar-just-fit is the 41.6K signal, the fact it's PWM, and the fastest z80 sampling loop I could come up with. It's /just/ fast-enough to be able to pick up every high/low in each bit (1 or 0), with /just/ enough margin to work when the CPU is running slower than usual. Weird.
Anyhow, then, of course, after transmitting, it'll expect a response. So it switches the wire to an input, and reception is similar-ish.
But, as I was saying before, this whole thing is very much a singular state-machine, no multitasking. Sample the 41.6kbps signal, parse the samples, calculate CPU frequency, transmit a bit, delay, transmit another bit, repeat 10 times, repeat for N bytes, receive...
It takes a different mindset, to develop an entire system that only does one task at a time, and each to completion...
So far I've got all that going... I haven't yet tested the 41.6kbps sampling/parsing/calculating AND the UART at the same time, since now I need to connect both the computer /and/ the device... I guess that's next.
It's also entirely plausible I'll never get the requests right to get a response... But, if that's the case, most all this work /could/ be applicable elsewhere. E.G. my "blacklink" cable, connected via USB-Serial dongle tops-out at "0.1K/s." Hah! I keep running into memory-fulls, which means something like 80KB of code to backup at 0.1KB(b?)/s is no fun... But, all this UART stuff could increase that speed dramatically... and, if i go that route with it, the autobaud code, which won't end up in /this/ project, would be quite useful.
Also, since I've made the UART pins configurable and overlappable, it shouldn't be too difficult to use the same uart functions on different wires at different times. So, e.g. the Calculator could support /two/ bidirectional 1-wire UARTs. So, e.g. it's entirely plausible developing the request/response code in assembly will just be too durn exhausting for me, especially since responses may not come to bad requests.
Heh. I actually got overwhelmed by that prospect a while back and said "F it, I know enough about the PL-2303 to know it /can/ be configured for custom baudrates... Why don't I just hook up the computer directly, and scrap the calculator idea? It'd give me logging, too." Yikes, sad albeit brief moment. Turns out my PL-2303 driver /doesn't/ implement custom bauds... I tried /really/ hard. But I'm not in the position to recompile my kernel. So, back to Calcy, kinda to my relief that I hadn't done MONTHS of work just to scrap it. So, if I just can't take any more z80 assembly, or run out of RAM, or decide I need logging in CSV's, I could just use Calcy a bit like I kinda saw it /before/ I remembered why I'd been looking for a handheld terminal in the first place... as a microcontroller that just happens to have a terminal attached.
If I'd've gone about this my usual way, I'd just grab an AVR and load up my UAR and UAT libraries, configure two of each on two pins, (Tx and Rx sharing pins? hmm, never did 1-wire with the AVRs... would that long-developed code support it?) one at 10.4, the other at 19.2, and with multitasking it'd just forward data from one to the other... Now's where the multitasking thing would be my default go-to... but, why?
The protocol is request/response, 1-wire is inherently half-duplex, this serial-forwarding /could/ happen at any rate... The computer sends the request at 9.6, the calculator repeats it at 10.4, grabs the response, retransmits it at 9.6. ... heck, even 1200bps would work (just to make my point that this is a singular state-machine, multitasking isn't necessary, here, even /with/ the intermediate data-forwarder).
So, an AVR would be easier (for me) and smaller and faster, and so-forth, but that system lacks something key to the end-goal... I can't always drive around with a full-on computer as its only interface. Calcy's a microcontroller with a terminal, project-box, batteries, etc that I can velcro to the dashboard. And connecting to compy for more fancy features at times is definitely an option. And, even using Calcy as nothing more than a baud-converter, at least while I try to figure out the request-protocol isn't a bad use of Calcy, but when I get that protocol figured out, I can assemble it up and leave the Compy out of the equation. Yeah!
We'll see. Next baby-step is connecting a potentially 12V pwm signal and a 3.6V UART to the calculator's link port at the same time... and wires dangling at my feet.
(I didn't have to worry about the PWM nor PL2303 voltage levels before, since I'm using the blacklink as a level-converter that also draws its supply voltage from its signals! How handy! Until you need two voltages.)
Hey, the engine may not be particularly happy, but it's keeping me warm, even through the recent snow! Which is more than I could say just a couple months ago. But, I kinda owe her a deeper diagnostic like this sooner rather'n later. Back to work, slacker!
-
Shouldn't've used a 555... a crazy ramble
12/06/2021 at 08:27 • 0 commentshttps://hackaday.com/2021/12/01/the-555-timer-contest-returns
There's a category for "Shouldn't've used a 555"...
This dang calculator doesn't have a high-speed timer of any sort, it seems, at least accessible by the CPU instructions.
That's why all these UART and other tasks have been really quite difficult, counting T-States.
One of my earlier thoughts was maybe there's an R/C circuit used to create the 200Hz interrupt. In which case I could tack an ADC on to get say 200×256 40,000ish ticks per second. It was mostly a joke, but I might've done it just to say I did, and maybe even figured out goofy ways to deal with those ticks' having different durations due to the RC charging curve. I'd've done it IF those beautiful ceramic and gold Analog Devices DIPs in my collection all these years were ADCs. Alas, they're DACs. Anyhow, Actually, now I think that 200Hz 200Hz interrupt is generated by the LCD driver).
But, 555's apparently go up to 100khz, which is even more ticks! Obviously, feed that into a TTL counter/divider, and yer set! But... inspired by the "Shouldn't have"... I actually hadn't thought of the TTL counter until just now. Heh.
Instead my brain went straight to trying to create the counter FROM 555's. And, actually, now that I think of it, even /that/ could probably be done... ripple-counter, each 555 has a latch. Probably, yep.
Nono, that's not where my brain went first, it went to trying to set up say 8 555 oscillators each oscillating at half the frequency of the previous. Yahknow, darn-near impossible to achieve precisely.
So, then it went to even weirder ideas, like vernier-scales and gray-code and beating... e.g. 8 slightly-detuned free-running oscillators (I'm choosing 8 because that's the bus width, not because I expect 256 values)... maybe even far slower than 100khz.
I hadn't really gotten much further than that before becoming /pretty sure/ something along those lines would be plausible... though a beast to decode in software, eh? Just the sorta way *not* to do a timekeeper...
OK, so, what, now?
I dunno, say you had three analog wall clocks with dying batteries. The second-hands would tick at slighly different rates, close to but not a second. Sometimes they'd seem to be in sync, other times completely out of sync...
No, shoot, this is exactly the opposite, right? Here's a fast pulsing, and a slow measurement from it.
No, wait, that works with the ~100KHz idea.
Right, so, the relative phases indicates the count of "seconds."
Heck yeah.
'cause, the whole point is there's ziltch liklihood I'd be able to read the port at 100khz to catch every tick. Especially when doing other calculations like bit-shifting serial data. But, we don't want to write that data bit to the port until 1/9600th of a second after the last one, so now when the bit is ready we can start polling our 100khz tick-counter to see when enough time has passed...
OK, I think there's something to work with, there... But, in the clock example one has to sit and watch the relative times between the /changes/ of the various second-hands to determine their relative phases, and /those/ occur *faster* than one second...
OK, now this is becoming a real challenge, the sort my brain won't be able to let go of.
... So, to recap: Analog wall clocks are a bad example. Just look at the position of the second-hand, or the friggin' minutes hand, if you want to know how much time passed since last you looked.
OK three metronomes.
This is a bad example, too, because allegedly they'll sync and stay synced(?!)
Pretend that's /not/ the case (seems absurd, would rule-out "beating").
OK, so, if they're all close to one second and they're all started at the same time... then for the first few toggles, they'll all pretty much be at the same positions at the same times...
I should start with two.
And I want....
To look at their /end-positions/ in order to determine how much time has passed.
So, if they're off by 0.25 seconds... then after 2 seconds pass they'll be at opposite end-positions, and after 4 seconds back to the same.
L L 0sec
R L 1sec
R R 1.25
L R 2sec
L L 2.5
R L 3sec
R R 3.75
L R 4sec !=0
R L 5sec =1
Wait, what?
Ok, so...
We're talking about interfacing this to a data bus, which would probably be best done via a latch that latches alongside *one* timer/metronome's transitions... the computer will only read back states at full "seconds" (why?)
LL, RL, LR, ... Wait... what?
L L 6
L R 6.25
R R 7
R L 7.5
L L 8
L R 8.75
R R 9
L L 10
LOL, I've got a friggin graphing calculator right here...
Anyways, i think i'mma wind-up mulling this over quite a bit more, whether I want to or not... but i think you can see the gray-code in there, eh? Also, quadrature (heh, was just thinking of #anaQuad! )
...
Somewhere in the vague-idea was the thought that maybe having 8 of them might mean that enough timing information could be extracted from them that their actual misalignment wouldn't particularly matter. Though, somewhere else in there it may be that we'd benefit from several 8bit latches to either store previous states or associate a separate 8-bit latch with each timer's toggling. Hmmm... nice thing... there's still a whole 1MB address-space available with its own dedicated chip-select! Hah, this is ridiculous... mind not switching off it, though. There's something interesting here, I just don't know what, yet....
Oh, something... that fractional *and* multiple tick measurements can be derived (from a single snapshot)? The 2-bit example only has 4 states, but with those we get both a multi-tick resolution of up to 2 and a fractional-tick resolution, as well.
So, e.g. say we need to measure up to a 4 second window with 1 second resolution, we could set one to 2sec and the other to 3sec (sacrificing the first second) hmmm.