• Links

    esot.eric19 hours ago 0 comments

    I've so many tabs open... and so many other bookmarks, this is in no way complete, nor in order. In fact, there are many great ones I've flat-out left out, since this was for tab-cleanup. Maybe I'll get back to this.


    ZAC, the z80 compiler, runs /on/ the TI-86. Also comes with an IDE and nice text-editor that also run on the calculator.


    This guy is reverse-engineering the 86 right down to gerbers of the PCB. This'd've been /really/ handy, if I hadn't found it so late in the game. Still... Amazing work, and surely useful.



    TI-85 schematic:

    crud, that was supposed to be a link.

    TI-85 Port Documentation (The T6A43 CPU is the same, including the ports... mostly.):


    There are two files at ticalc.org for the 86's ports... I should dig up their links... those three docs work together to paint a better picture of the T6A43's ports, in general.



    ... stuff here:



    Great Resource, all 'round the site, for z80 stuff, ASM, stuff, TI-OS stuff, and TI-86 programming:


    Z80 instruction set:


    Z80 ASM stuff:



    TI-86 Programs:


    Random goodies:

    TI-86 with an STM32?!!!


    I dig the hardware-hackery-enthusiasm in this thread... most forumstuff I've found seems mostly limited to writing games, etc...


  • Binary Decimal Connection

    esot.erica day ago 3 comments

    discovered something interesting today that could be quite useful to remember for the future... surely would've come in handy in the past!

    I've been doing digital circuits and embedded software design for well well over two decades... so I'm not a noob... so, I'm at a complete loss at how something so obvious has eluded me all these years.

    Though, I'm not really sure how to put it into words... maybe a table is coming...

    1 bit can have two values (0, 1)

    2 bits can have 4 (00, 01, 10, 11)

    8 bits: 256

    I've got them all memorized up to here. From there on I usually grab a calculator (2^numbits) or use some tricks... e.g.

    10 bits: has two bits more than 8 bits, 8 bits is 256, two bits is 4, so 10 bits is 256 times 4 = 1024

    I always thought it a bit interesting that 2^10 is 1024... the connection between 10 and the binary equivalent of 1000, or 1k. 

    But, I kinda likened it to the interesting features of 2 in that doesn't seem to occur with any other numbers. E.G. 2+2=4=2×2=2^2... but, none of that works for 3 nor 1. So, surely 2^10=1k is a fluke, right? Always just chuckled at 2^10 when I ran into it, then moved-on.

    Today I needed  2^18...

    OK... 1024 * 256 = 256k. Hey wait a minute...

    Surely that doesn't contin.... uh... why wouldn't it?

    Hey, first-off, I'm no moron, well, I probably am... but I can see patterns /that/ glaringly obvious, if they stare me in the face for 20 years... I have an excuse... I /usually/ only need these sorts of numbers when dealing with address bits... and, usually, we do that in hex... and usually address bits are numbered starting with 0.

    My FLASH chip has 18 address input bits. Its last address bit is A17. 2^17 is 256K?! Wait a minute... no... 2^18, 18 bits used for addressing. gah. Ok, move on.

    So, if you're looking at a device with A19 as its highest address bit, then it stores 2^19=mathTricks=512K... but, wait, that stupid datasheet says 1MB. GAH! I forgot A0, again. It has 20 address bits, it's 1MB... interesting how 2^20 gives a nice round number in binary terms... I mean, it coulda started with 6 or 3 or... I mean, look at the highest value that can be stored in two bytes... 65535? Really? I mean, even in binary terms it's weird, 16 -> 64k? Doesn't really correspond with anything other than 2 bytes.


    10 -> 1K, 1024 ~1000 (if you sell hard drives)

    20 -> 1M, 1024*1024=~1,000,000

    30 -> 1G, 1024^3=~1,000,000,000

    40 -> 1T, 1024^4=~1,000,000,000,000

    WAIT... So 2^n... 2^(a*10+b)...

    2^42 ... 4 tens, 2 ones

    4 tens is 1024^4... that's... 1, kilo, 2 mega, 3 giga, 4 tera... ok...

    2 ones is 4... 2 bits is 4 values

    42 bits, then is 4Terabytes? It's /that/ easy?!

    So, one more time... 2^ab, where ab is a decimal number... a is the number of tens, b the number of ones... maybe we should use 2^xi, instead... or XI

    64 bits, X=6, I=4 gives:

    6 whatever they're called... postfixes... 1 Kilo, 2 Mega, 3 Giga, 4 Tera, 5 uhh... 1024T, 6 whotheheckknows, 1024*1024T... we'll call it 1FollowedBy6setsOf3zeroesWhichAreReally1024s

    <s>And 2^6=1,2,4,8,16,32.

    So 64bits has 32F6 values.</s>

    Friggin' don't count "1" in 1 ,2,4,8,16,32,64... 1 bit has 2 values, not 1. See the same mistake, again, below! 64F6 values.

    Ok, maybe it's not so simple... but for kilo, mega, and giga, I think I can wrap my head around it pretty quick:

    32bits 2bits=4vals, 3: k,m,g. 4GB

    16bits 6bits->32vals, .... Wait a minute...

    2,4,8,16,32... no 64. Friggin "bit 0 has two values". 10, of course, is k... 64k. (Thought I had those memorized?)

    18bits, 8->256, 10->k

    22bits, 4 M

    27 bits, 128... M

    31 bits, handy for knowing whether you'll approach the limit of a signed 32bit integer... 3=G~=1,000,000,000~=10^(3*3), 1bit->2vals, so roughly (and with a safe margin) the maximum value you can store is 2 billion.

    24 bits... There've been numerous of my 8bit projects where 65535 wasn't nearly enough, but 32 bits was a tremendous waste if you think about not only the memory that'll never be used but also the extra addWithCarry,...

    Read more »

  • "Not A Hack"

    esot.eric2 days ago 0 comments

    well...  I mean... really... If you consider the T6A43 Z80 VLSI as a bit of a microcontroller, and if it were officially documented... then the only real "hack" I did, circuit-wise, was figure out a way around its lack of an Output-Enable on the I/O bus. 

    Toshiba's "hack", therein, was apparently to not assign a pin to it, despite its being de-facto on the Z80 inside. Assuming, I guess, most RAM/ROM chips don't really need it. It, from the devices I've checked, (TI's RAM, ROM, and my vague memories of most other such-interfaced memories I've used in the past), can be tied active in most cases, wherein ChipEnable does the job of preventing output, and WriteEnable overrides output. There may be a little room for bus contention during the brief period between enabling the chip and loading the data to be written before the device can disable its output in response to WriteEnable... but, probably minor, and maybe even moot due e.g. to the propagation-time for output in the first place. OK, I think I can buy it as a design intent.

    TI's "hack" was similar to mine, it seems, in how to drive the /OE on the FLASH chip they apparently used during devel of the TI-86... That chip differs from the others, in that /OE must be inactive to enable writing. No /OE, most devices' /OEs being constantly active... now what? Yesterday I linked a page which, as I recall, shows /OE coming from some logic fed by Chip-Enable 3. But I've reverified my board's traces, and I don't see /OE anywhere but the ROM and a strangely-located pin on the T6A43. I watched it with a logic probe under many conditions and never saw it change. Which makes sense if it's a hack for the FLASH (which mine doesn't have, an OTP ROM in its place, instead), but of course would /not/ make sense if it really was the Z80's /OE. (It'd toggle with RAM accesses!)

    So, I've yet to find its source in software, but it very well may be nothing but a currently-undocumented general purpose output e.g. from an unused bit on the link port. And, of course, we never see any other value on that bit nor pin other than 0, because my ROM/OS version is designed to be run from an OTP PROM.

    My '86, however, /does/ have an unpopulated IC that looks to select the ROM (or FLASH, in the devel edition) when /either/ CS0 or CS3 is selected. So, my thought is they used /CS3 when writing the FLASH and /CS0 to run code from it. (HMMM, but if OE is disabled /during/ a /CS0 access, say to execute the code to program the flash, then nothing would come through! This doesn't make sense! Presumably they'd run that code from RAM... with Zero ROM function-calls... but if they did that, then /CS3 would be unnecessary! Unless, maybe, internally the VLSI blocks WriteEnable with /CS0? Huh. The other guy's makes more sense... use CS3 AS Output Enable).

    Anyhow, I opted for similar in my only "real hack" in this endeavor of adding 256K of FLASH. I assigned A18 to Output Enable.

    OH OH OH OH! HAH! More on that in a bit.

    I'd originally planned to use /CS2 for reads and /CS3 for writes. Then /CS3 would be directly-wired to /OE. Badda-bing.

    (Double HAH! Somehow I'd missed that I'd have to OR /CS3 and /CS2 to go to its ChipEnable input!)

    But, I decided, instead, kinda late in the process that I didn't want to waste a dedicated Chip Select which could be used in another add-on.

    So, I decided to wire-up A18 to /OE... and since /CS3 was already broken-out to the unpopulated IC's pads, I used it for my FLASH's Chip Enable. Great! Now the FLASH looks like 512k instead of 256 to the Z80 VLSI... one half is read-only, the other half is that same data, at the same locations in the chip itself, but write-only. Great! That works for my needs... and it's not like 256k of extra address-space usage is a big deal. Heck, it'd've been occupied anyhow, without additional address-decode logic. And there's still a whole 1MB left with /CS2.

    Heh, so coming back to the big shock I had earlier... Using a chip-select for /OE meant...

    Read more »

  • 32 pages, and then some! 4MB!!!

    esot.eric3 days ago 2 comments

    No joke, it seems I was spot-on about the unused pins.

    So, yes, indeed, I /could/ wire up the new FLASH to use 128K above the RAM, call it "RAM pages 8-15"... Add a tiny bit of glue logic on its and the RAM's /ChipSelects...

    OR, I could wire up the Flash's chip-select to... Duhn duhn duhhhnnn... The Z80-ish's unused /Chip-Select2 or /Chip-Select3. Piggybacked atop the built-in ROM, we're talking two bodge-wires (/CS2, and /OE... from somewhere... heck, I could use /CS3 /for/ its /OE), and no need for glue logic, nor popping pins of other devices. Heck, even /WE is there to be piggybacked.

    Anyhow, I was also right about the two additional address bits. This thing's designed to map in four devices each up to 1MB. 4MB! WOW!

    And, something weird... U10 is unpopulated and bypassed with a zero-ohm resistor at "S4." U10 appears to be a one-gang 2-input OR(?), its inputs tied to /CS0 (the ROM's chip select) and /CS3 (which is selected by writing both bits 6 and 7 high in port 5 or 6). Its output is connected to the ROM, at its chip-select. So, apparently, for some reason they had the ability to map the ROM from two places(?). This /Almost/ sounds like my idea for bodging-in the seemingly non-existant (and necessary for FLASH writing) /OE. Huh. 

    I tried, a little, to figure out the /OE pin they /did/ wire to the ROM; it's so near the LCD signals and so far from anything else bus-related, I thought maybe disabling the LCD would toggle that pin, a wild hack on their part... but, nah, nothing I did turned it off (it seems it never goes high). wait...? ... no... not even selecting a different device in the "ROM" page... right? Wait, did I do my tests with port 5 or 6? Hmmm. Gah, I wonder if it's an extra bit on the "link port" which just happens to never be written high...

    Anyhow, there are /plenty/ of options with 3.625MB of unused address space to work with!


    The Display: The T6A40 row-driver on the back of the LCD does, indeed, toggle its carry-output. That means it's receiving more than 68 clock pulses. This looks good for my display-hack-for-general-purpose-outputs idea. Though, the thought occurred that the default address for the frame buffer, being at 0xfc00, causes the legit pixel data to end at 0xffff. IF I'm right about the display driver's continuing to spit out RAM data during lines 65-68 (and, obviously above), then where's it getting it from? I tried disabling interrupts, so nothing was running from the ROM, and... I didn't see any ROM chip-selects... so it's not wrapping to the Z80's address zero. Is it possible it works with the RAM's addresses, directly? Then, Oh Wait. The framebuffer mapping port, as I recall, adds C000 to whatever value you put in for the high address byte... C000, of course, being the beginning of the permanently-mapped RAM page 0. So, it probably wraps to RAM-address 0 = z80-0xC000. Duh. That, unfortunately, would be much harder to check with only a logic probe... though, actually, having been an oscilloscope guy from an early age, I'm quite pleasantly surprised with how much can be determined with nothing but a logic probe and a different way of thinking. Maybe I'll come up with something, if I decide to go that route. (I've got a 'scope I love in storage).

    One thought for a /use/ for this idea is quite simply snagging a second identical display, maybe find an otherwise busted TI-86 somewhere, and daisychain them, vertically. Most-likely the '86 isn't outputting 68+64 rows, maybe only a handful more, even, but... even tapping those 4 extra rows could be handy for, say, status icons. I /think/ the display could even function after being cut with a glass cutter... something I've wanted to try for quite some time... making use of the still-usable portion of old cracked displays.

    Other ideas have been described in past logs, adding a shift-register (or 7) to snag that data and turn it into outputs. Not really necessary, now, with two unused chip-selects, and 2 unused address...

    Read more »

  • Memory Cleared, take 3

    esot.eric3 days ago 0 comments

    now, how is that even possible? The backup battery is now internal. I tested it /several/ times, opening/closing the case, swapping main power-sources...

    Today I loaded up ZAC and ASMIDE again, popped open the case, and it was wiped again!

    So I tried several times to repeat the wipe through the actions I'd taken earlier... and... nada. Thing holds its memory fine despite everything I threw at it. Pulling the batteries when it was on, pushing "On" when the capacitor was discharging, plugging in the external battery pack, unplugging it, opening and closing the case... nada. Memory Not Cleared. 

    Frustrated with that one time of unrepeatable flakiness, I decided to just logic-probe-around anyhow, get the jist of what it does when it's empty and sitting at the blank prompt.


    Yeah. I crashed the thing hard, several times, shorting pins while probing. And I was being quite careful.

    This is no easy task, working on this thing's hardware!

    Again I'm half-tempted to just assume I'm right about being able to piggyback my FLASH chip atop the ROM, and a tiny bit of Glue-logic to map it in the 128k above the RAM... but... that just doesn't seem very scientific-methodological to me. And, besides, I was kinda hoping to map it elsewhere, which would require a different glue-configuration, and less-likely unused pin functionality that should probably be tested first. I dunno. 

    "Memory Cleared" is a pain!


    WHat On Earth?!

    Now it's starting up saying "Memory Recovered"?!


    Days, and MANY uses later: Found this: https://www.ticalc.org/cgi-bin/zipview?86/asm/programs/zac.zip;Zac.txt

    Nice One, ZAC... saved the day many times over.

    Crash protection
       When a compiled program is run with the "[ENTER]=Run" command, crash
    protection is installed before execution. It is a very limited anti-crash,
    and it will not work if it's a serious crash. If you see that your prog is
    crashing, or behave strangely, press ON, and you'll return to the homescreen
    (hopefully...). If your program is really buggy and the calc crashes, remove
    one battery, and put it back. Then turn the calculator on, as if nothing has
    happened. If you see the "Memory recovered" message, then you didn't lose
    anything :)
    WARNING: It doesn't work every time. Be sure to backup any important files
    before trying a program.

  • Soldering Complete! AND What is the draw to CP/M?

    esot.eric4 days ago 4 comments

    MANY DAYS (Weeks?) as The One Big Plan for the day, upon waking each morning... and still left with it on my mind upon going to bed. Heh! What was it... eight solder joints?

    I now FINALLY have a means to power the thing while it's open, as well as not wipe its memory by opening it. I scaled-back the plan quite a bit. I have test-clips, but installing them without shorting pins is /very/ unlikely... so, I'd planned to solder leads to the pins I plan to test. Instead, on a whim as the sun began setting, I wired the cable to the external battery-pack through the switch that was already in it... (Why would I want a switch on the main power supply of a system which sleeps when "off"?!) Only after that split-second last-minute decision was implemented did it occur to me... hey, if I cut the power, I can install the test-clips [almost] wherever I want and not have to worry about shorting nearby pins in the act! Nor do I need to be limited to only the pins I pre-soldered leads to! Holy schmoly, brilliant!


    WEEKS, maybe, to solder in an internal backup battery, a header for a power supply, and some leads to a battery pack. Hah!

    I think, maybe, now I can finally code-up somethings to/and test those pins.


    In other news, I just scrolled on a Z80-based CP/M machine designed recently which has just a handful of period ICs aside from a Compact Flash card... and it got me to thinking...

    What Exactly Is (or was) The Draw To CP/M? It's a sincere question, being that the past several weeks of non-progress on the front I'd been planning have instead resulted in my gathering all sorts of ideas how to design my own stock-z80-based computer... I WOULD'VE thought (rather, /did/) that the crazy sorts of implementations I've come up with would be far too architecturally different to enable running most z80-based era-computer-programs... E.G. my vidcard idea of a recent log, surely loadrunner wouldn't run on that...? But Then... I start seeing these CP/M compatible designs that folk've come up with that are nowhere near architecturally similar to, say, my Kaypro... and... well... then I start thinking, well heck, there were /numerous/ z80-based computer systems in the CP/M era, and they varied dramatically, yet they mostly ran CP/M, right? Yet, they couldn't run each others' programs, no? So... then... what /IS/ CP/M...? What does it provide, besides a common look in directory-listings? Can /some/ CP/M executables run on /any/ machine running CP/M? While still others can't because, say, they might try to directly access hardware that isn't there? I just don't get it. And, if the former... what types of programs would be universal like that that folk would want to run on their otherwise custom machines? So far, I see Fortran, Assemblers, and C as possibilities, maybe some serial-communication programs... Text adventures? Surely even most text editors would require finer/lower-level interaction with a screen than stdio provides. I'm not trying to discredit the idea, I'm just trying to understand, maybe even consider trying to implement it on my design, if I can figure out why... what's the draw to running CP/M? What all does doing-so offer?


    In a similar realm, I recently saw DOS running on an 8086 in... well, heck, I forget the name... but, basically the 8086 has two modes, an easy mode and a hard mode... one requires a LOT of external circuitry, which is the one PCs is based on. The other is far simpler, but removes options like DMA and such that... I thought... DOS relies on. So, again we're back to the same question as for CP/M... what on earth would be the draw to running DOS on a system so architecturally different that the vast majority of software written for DOS can't run on such a different system? At that point, isn't it basically just a slightly more sophisticated BIOS that basically implements disk-access and little else? Heh, and DOS gets all the credit, when, frankly, most applications of the era had to be so deeply-coded...

    Read more »

  • I got THIS far...

    esot.eric6 days ago 3 comments

    Hm... no rotate?

    OK, so look at how perfectly a backup battery fits in there, leaving accessible almost every pin I plan to probe! Amazing!

    I noticed something very strange about the backup battery implementation... I dunno how much steam I have to describe it except to say that it's wired-up with a common Positive, rather than ground. And it required hooking up the battery and measuring voltages to figure out. The key factor is that when the main batteries are removed, there is no voltage source for the rest of the components (Z80, ROM, Display)... so, the voltage across /their/ V+ and /their/ ground is 0V. Since their V+ is wired directly to the backup battery's V+, that means every pin on every non-powered device is at roughly +Vbatt with respect to the /SRAM's/ ground. Thus, /CE1 on the SRAM is pulled high through the Z80's being off, but connected to the +Vbatt rail. 

    This goes against all my instincts. If /any/ current is drawn through those pins (ALL of the bus pins, mind you, at roughly Vbatt) then, it seems to me, the whole shebang collapses.... because now that current puts a voltage drop across V+ and those pins,... and, at the very least, causes the output voltage to vary... and that can be seen already. According to the RAM datasheet, /CE1 must be at or above VCC-0.2V to go into standby... VCC is around 2.7V, /CE1 around 2.4V... we're already out of range. And, that extra 0.3V? Isn't it powering the other devices in a really bad brownout /through/ the outputs?

    K, then there's the other factor... when I first measured the voltage between the backup battery's ground and the system ground, I got a /higher/ voltage than the battery is outputting. 0.2V higher. Weird. I reproduced it for a few attempts, but as I began to trace it down, it didn't add up. Then things started getting even weirder, the voltages on the RAM's inputs, especially /CE1, (from the unpowered z80) started getting even further from the VCC-0.2V minimum! All the way down to 2.2V before rising back up to 2.3, and I never did see 2.4 again (nor ever saw the 2.5 minimum).

    Turns out if i touch the system ground, with my finger touching one meter probe, and touch the other with the other finger to the RAM's ground, the /teeny/ current flowing through my body was enough to affect the voltage the z80 is sitting at... and... actually put some voltage across it. Hah!

    I dunno... i mean, it's not exactly going to run into such conditions when it's sealed up... but something about this all seems strange.

    Oh yeah, there's also the bit about how the RAM's ground is always 0.3V higher than the other devices, due to the diode, under normal power, and so therefore can see input voltages /right/ at its Vil-min limit of NEGATIVE 0.3V.


    This is not at all what I planned for my day. I was going to solder! Too late now, gotta pack up.

    Then I got all sidetracked on how transistors work... couldn't get my mind off it. Nothing related came of it, but I think I may've come up with an interesting "guitar effect"... not that I know anything about those... wherein the positive half of the waveform is undistorted, but the bottom half is... deamplified. Wonder what it'd sound like...

    ... "Time to pack up..." which sucks, because it's just about right now I actually have the soldering energy.

    ...Oh yeah... this all came about because I was looking for solder points that would be out of the way and strong enough to support a pin header. Hah! I almost forgot.

    Oh Oh! There's a friggin' capacitor to ground on /WE...! WTHeck? My guess: to prevent it from writing randomly when powering-up the z80... but, seriously... what? Mind you, that same trace also goes to the ROM, for writing when they were in development, and used FLASH instead. So, yahknow, nothing like slowing precisely-timed signals... which is also a plausible explanation, being that /OE isn't used, the timing may be a bit funky, so delaying /WE may be useful to assure it stays active after...

    Read more »

  • Z80 Memory Refresh Cycle for LCD refresh? Getting carried away...

    esot.eric7 days ago 0 comments

    The Z80 has an interesting feature in that it's designed to automatically refresh DRAM after each instruction-fetch.

    The process goes: fetch instruction op-code, then while processing that, refresh the next row in the RAM. It handles 128 rows, incrementing through, then repeating. Thus, during the refresh portion of every instruction, the address bus outputs one address from 0-128, in sequence.


    Then, apparently it was somewhat common to hack that a bit for larger memories, e.g. adding a flip-flop or a counter to handle higher address bits for DRAMs that had more than 128 rows.

    But... there's no reason the same couldn't be used for /other/ purposes than refreshing DRAM.... and refreshing /displays/ would be darn-near the perfect use! 

    That might well also explain why the (static) RAM's /Output Enable is always active (wired directly to ground). So, in the case of the TI-86 display, 128x64=1024 bytes... 128 on the refresh counter, with three extra flip-flops as a three-bit counter... and now your DRAM refresh is turned into a framebuffer-access for refreshing the LCD. Attach the LCD's "load row" input (essentially hsync) to address bit 4... a /tiny/ bit of glue, maybe, to delay the next loading of 8 pixels until a few nanoseconds after the hsync... and, that's basically all it takes! Oh, and the z80 /refresh output is wired to the LCD's "load [pixel] data" input.

    And, it doesn't slow /anything/ down, as far as CPU overhead.

    So, it probably wouldn't work with VGA, CGA, MDA, HDMI, etc. Since they rely on steady pixel-clocks... and, I think, the DRAM refresh only occurs once per instruction-fetch (which would vary in duration depending on how many bytes are in the instruction) but minor circuitry and it'd probably work with most "Display Parallel Interface" LCDs, and most of the older graphical LCDs which are similarly interfaced except typically load several pixels with each "pixel clock". Just like the TI-86 and TI-85 (And TI-81, I presume) displays, which load 8 pixels at a time.

    Basically the stock Z80 has /most/ of a graphical LCD controller built-in. How cool is that?!


    Now, here's some other hackery-potential gathered from what I've read... Increasing the Timer-Interrupt frequency, say by 2x, causes the LCD to display the first half of the image twice. Apparently the timer-interrupt resets the LCD's row-counter. What does this mean for hackery? 

    In an earlier log I discussed the idea of using the LCD itself for general-purpose outputs. One method is to consider the fact that the row/column drivers in LCDs of this sort of interface are completely unaware of the screen dimensions. So, say, outputting a 160x64 signal to a 128x64 display would simply display the first 128 pixels on each row, and the remaining 32 would be shifted-out the "carry out" outputs of the column-driver chips which, then, could be fed directly into shift-registers of our own, and offscreen data in the framebuffer could then be used to drive outputs for any purpose we'd like. Turns out the column drivers on this LCD are actually designed for 160 pixels, but only 128 are used... and the remaining 32 are physically inaccessible... and the "CPU" seems to only be configurable to 160 pixels. So, that idea is pretty much a nogo.

    BUT... Since the timer-interrupt is apparently responsible for resetting the row-counter (and, presumably, sending the "frame" signal, which is equivalent to Vsync, but in my experience tends to get ignored if it comes too soon, which appears to be what's happening to cause the screen data to duplicate, rather than just get cut-off and start again at the top... e.g. if the row drivers are made for 64 rows, then they assume you'll send at least that many rows, before paying attention to "frame")... 

    Then... What this all likely means is that the display is really being driven with some /random/ number of rows, greater than 64... and that it just ignores the extra that come in until the next...

    Read more »

  • FLASH backup plan

    esot.eric07/18/2021 at 23:17 0 comments

    I think I've worked it out... and, frankly, I'm surprised not only at how easy it should be, but also some inherent factors of the system design that should make it even easier.

    First-off, we're talking /full/ RAM backups to FLASH... why? Mostly because I've little interest to try to learn about TI's variable system, which I think is also responsible for storing programs, etc.

    Again, this endeavor is, to me, little to do with the calculator's original functionality, and more to do with what new ways it can be used. One of which, for me, is learning about Z80's and Von Neumann architectures, which applies to /many/ systems... wherein TI's OS is useful and a learning experience in itself, but learning /it/ is a bit less useful.

    All that to say, the backup FLASH will pretty much simply duplicate the entirety of the RAM, stack, variables, running program, other programs, text buffers, frame buffer, and all. Why not?

    Restoring from a memory-clear, then, is simply entering about 6 hex values and running it through AsmComp() then Asm().

    Basically it amounts to: Load FLASH Page 0 ("RAM" page 8) into the "RAM" page slot, then jump there. And that's it. I think 6 bytes, 12 characters to enter by hand, total.

    Now, once it jumps there it begins executing the real program, which, simply, copies the entirety of the FLASH to the entirety of the RAM, byte for byte.

    But wait! That'll overwrite the stack and stuff already in the RAM! ...And? Once it's restored, it should basically act exactly like it did once the original backup was completed.

    So, then, how am I going to know where in the backup to find the recovery-app to jump to in the first place, if I'm not going to learn about TI's variable lookup table, etc.?

    OK, so dig this: The backup and restore program are one and the same. Running the backup program loads it into _asm_exec_RAM. That means the program is loaded and running from there WHILE the backup of the entirety of the RAM is performed, including a backup of the running program /as loaded into RAM/.

    Thus, When Restoring, we know exactly where to jump in the backup image to run the restore program from within the backup image itself.... (_asm_exec_RAM - 0x4000). Minus 0x4000 because _asm_exec_RAM is in RAM page 0, which is at z80 page 3, but the FLASH page 0 will be mapped to ... actually, I should probably map it in the "ROM" section, z80 page 1, so minus 0x8000, since we'll need to map all the pages from RAM to back them up.

    But wait! If you're executing from FLASH, then how you gonna switch in the FLASH pages to backup to/restore from?

    Ahh, but see... The first step is to copy the first page, which happens to contain _asm_exec_RAM, which is always mapped in at z80 page 3. So, after that first page is copied, we resume execution not from the FLASH, but from the duplicate now where execution normally happens, in the RAM.

    So, inherently, we know where to execute from when it comes time to restore. No need to learn about the VAT, nor how to load and call an assembly program from within an assembly program, etc. No need for a special utility to copy each individual file...

    I think I can do this. Assuming, of course, the "RAM" option in the mapping ports /can/ actually make use of A17, as the "ROM" option does. Which, again, is something relatively easy to check, I just need to actually get to it. Main thing there is I need to wire-up reliable power so I can load ZAC, then get to coding, with the case open, most-likely, then use the ol' logic probe and hopefully not short anything causing a Mem Clear. I can do this...

    Heh, I'd been thinking to wire a USB cable for power, then use a USB battery pack... but, those "shut off" when the current draw is too low, as might likely happen during power-down... "Mem Cleared". And the button cell goes in the back of the case... AAAs it is, I guess!

    It's kinda funny to try to equate this to a z80-based computer.... imagine having had enough RAM to store all your programs...

    Read more »

  • Memory Cleared Defaults Set, part 2

    esot.eric07/17/2021 at 04:38 3 comments


    My program was bordering on 200 lines, painstakingly entered by thumbs twiddling meta keys mistakenly at many wrong times, backspacing, re-entering.... 

    Built me some of my first libraries, a hex-printer... but, yahknow, didn't back-up during my roll, and now it's all gone.

    I did get one thing tested, though... wrote 0xff to port 5 and 6, and read them back, as well. So... technically, reading back a register means two things, A) there's a register there, and B) it was designed /to/ be read-back. That means those ports actually have registers on the otherwise allegedly "unused" bits... so, why would they do that if they don't go anywhere? Could've been laziness, slapping a "block" down in some ASIC CAD program... but this chip is pretty old, did they even have such programs back then? And, otherwise, it'd've been cheaper not to go that route... so, I'm still led to believe it's entirely plausible there's room for expansion, here. At the very least, an extra 128K untapped with the "RAM" chip-select, but I'm still thinking even more; that wouldn't require any more than the documented bits on those mapping ports.

    Anyhow, this time I think I managed too many 'pops' from the stack. Last time it was having forgotten a 'ret'. People really code like this?! I mean, it'd be /easy/ to muck up a running OS with these sorts of mistakes! We just rely on the idea it'll crash hard, but [most likely] only affecting RAM, so will reboot OK?! No worries about damaged hardware? Heh. Look what it did to the screen... that just ain't right. Those pixels are definitely not "on."

    And not off, either.