Converting a Franklin ACE 1000 to monochrome

The Franklin ACE 1000 didn’t originally support color, due to an Apple patent on the skeevy color-burst generation circuit.

Franklin eventually worked around this by shipping a daughterboard that plugged into the character generator ROM socket and had a few flying leads to strategic spots on the motherboard. The daughterboard (aka “color board”) bypassed most of the motherboard’s video generation circuitry, and delivered a color video signal that was decidedly inferior to that of the Apple circuit.

Prior to the introduction of the color board, it was common to add the missing components to the monochrome motherboard to replicate the Apple circuit. The procedure is somewhat laid out on page 57 of the “Franklin Service 1 of 2” PDF available on archive.org, but it omits a few very important bits.

I have both a monochrome ACE 1000 (modified for Apple-ish color) and a color board ACE 1000. The video on the latter is, frankly, quite shitty in comparison to the former.

I undertook to convert the color board ACE to mono, with an eye towards creating a kit to make conversion mostly painless. This is a write-up of my notes on converting a color ACE to mono.

First, the color ACE removed a number of components from the motherboard — this makes sense, as the color board bypasses them and thus they were not populated. The following components will be needed:

  • ZA4: 74LS166
  • ZA9: 74LS257
  • ZA10: 74LS151
  • ZA11: 74LS194
  • ZA12: 74LS74
  • ZB4: 74LS194
  • ZB9: 74LS194
  • RJ6: 2k 1/4-watt resistor
  • RJ7: 1.5k 1/4-watt resistor
  • Q3 2N2222
  • 2716 or 2732 EPROM

There will be small PCBs in the ZA4 and ZA9 sockets; remove them and replace with the appropriate IC.

The Q3 footprint will have two wires soldered into the pads; remove the wires and replace with the transistor.

RJ5 needs to be decoupled from ground. Don’t remove it completely, as the colorburst signal will eventually be fed into Q3 through it, just desolder that leg and lift it off the motherboard.

The color board’s chargen EPROM will not work when plugged directly into the motherboard, as it’s a 2532 and thus not-pin-compatible with the motherboard’s 2716 socket. Burn the bottom 2k of the stock color board EPROM into a 2716 (or twice into a 2732) and use that on the motherboard.

Side note: the lower half of the Franklin chargen EPROM data is byte-for-byte identical with the “Apple II+ – Lowercase Character Generator – 2716.bin” that Henry has made available at https://downloads.reactivemicro.com/Apple%20II%20Items/ROM_and_JEDEC/II_&_II+/. I should contact Henry and ask about the provenance of that binary — it would be interesting if it was originally sourced from Franklin gear. The upper half of the EPROM contains data that’s only valid in graphic mode (I haven’t reverse-engineered the color board to determine why that is) and can be safely omitted from the 2716/2732.

Pin 1 on ZB14 needs to be isolated from pin 2 and connected to the color burst signal generated by the clock circuit. The easiest way to do that is to lift that pin and solder a flying wire to pin 3 on ZD1. A cleaner method would be to cut the trace between pins 1 and 2 on the bottom of the motherboard and run the wire underneath.

At this point the ACE should be fully converted to monochrome-only video.

The new color circuit should look like this:

That circuit is a synthesis of the handwritten notes in the Franklin service manual, the color schematic in the Red Book, and what I found in my mono-modified ACE. I’m waiting on the 27uH choke and the variable capacitor to arrive before I can prototype this, but it’s relatively straightforward:

  • the colorburst signal is picked up off pin 12 from ZB12, run through a LC filter, and fed into the output video amp,
  • Q3 gates the colorburst signal by the state of TEXT/GR (picked up from pin 2 of ZB14), providing the “color killer” functionality added to the Apple ][+,
  • the COLOREF signal from the clock generator is factored into the NOR gate

I’ll update this post with the color circuit procedure when I have this nailed down.

Posted in Franklin | Leave a comment

Sam’s Jam (Commodore 64 game)

When I was a teenager, I used to hang out at Digital Test Systems (the local Commodore dealer / warez hub) and play pirated games.

One of my favorite games was a British platform-type game called “Sam’s Jam”. It appeared to have been ISEPIC‘ed, and often crashed after clearing the first board. Clearly it was an incomplete crack.

Over the years, I have tried off-and-on to find a clean copy on the Internet, without success. I finally bit the bullet and purchased a tape from eBay.

I converted the tape to .tap via my Ultimate64, cleaned it up via tapclean, converted it to a single-load .prg, and put that .prg onto a slushload .tap and a .d64 …

… it’s available here.

Posted in Commodore | Leave a comment

Analog NTT CallerID with Asterisk/DAHDI

There is a lack of extant documentation (both Japanese and English) to configure Asterisk to detect CallerID on NTT analog lines.

Below is a configuration set that works for me. The analog card is a Taobao/AliExpress-sourced AEX410 clone. Digium likes to remove support for cards that it no longer sells from their official drivers, and the Linux kernel developers like to gratuitiously break driver APIs … which means that Digium drivers with AEX410 support (or TDM4xx support, etc) can’t be used with modern Linux kernels.

I’ve forked the Digium drivers, forward-ported wctdm and wctdm24xpp support, and placed the source code on GitHub here.

/etc/modprobe.d/dahdi.conf:

options wctdm24xxp boostringer=1 opermode=JAPAN

/etc/dahdi/system.conf:

fxsks=1
echocanceller=oslec,1
fxoks=2
echocanceller=oslec,2
fxoks=3
echocanceller=oslec,3
fxoks=4
echocanceller=oslec,4

# Global data
loadzone = us
defaultzone = us

chan_dahdi.conf preamble:

[channels]
language=ja
transfer=no
canpark=no
cancallforward=no
callreturn=no
immediate=no                ; give Asterisk time to get CallerID
usecallerid=yes
cidstart=polarity           ; NTT reverses polarity for CallerID
cidsignalling=v23_jp        ; NTT uses v23_jp
echocancel=yes
echocancelwhenbridged=no
echotraining=no
busydetect=yes
busycount=15
answeronpolarityswitch=no   ; give Asterisk time to get CallerID
hanguponpolarityswitch=yes  ; NTT reverses polarity on hangup

; FXO port 0 (Asterisk port 1)
signalling=fxs_ks
rxgain=3.0
hwtxgain=disabled           ; hardware gain settings screw up CID
callerid=asreceived
group=0
context=inbound
channel => 1

… if you have more analog lines, tack them onto the end.

That should do the trick.

Leave a comment

Fixing Litter-Robot 3 Connect network issues

The Litter-Robot 3 Connect is a rather well-designed self-cleaning cat litter box. I’d used a previous version about a decade ago, and am pleasantly surprised at how well the current incarnation works.

One of the main selling points of the LR3 is that it can be controlled via an Android app. There are a lot of complaints about the LR3 frequently dropping off the network, requiring a powercycle to reconnect.

I have a TP-Link TL-WR940N that has been flashed with OpenWRT, so I’m in a position to troubleshoot this problem. I turned hostapd debug up all the way, and started poking around.

I have identified three issues that cause the LR3 to stop working.

First, the LR3 can’t handle 802.11n. The wireless access point must be configured for legacy (802.11b/g) mode only. That fixes the “immediate disconnect” issue.

Second, Wireless Multimedia Mode (aka “WMM”, aka “WME”) must be disabled. WMM has a sub-feature called “Power Save Certification” (“APSD”), which (according to a Netgear techpub):

“… uses mechanisms from 802.11e and legacy 802.11,to save power (for battery powered equipment) and fine-tune power consumption.

“This feature of WMM to save power might cause disconnects under certain
conditions.”

That solves the “disconnect after thirty seconds” issue .

The third one is the most important: if the wireless access point hasn’t seen any packets from a client for awhile, it will send an empty data frame to the client to see if it is still there. By default, this packet is sent five minutes (300 seconds) after the last client packet was seen.

If the client doesn’t respond, the access point will deauthenticate the client. It is up to the client to re-authenticate.

The LR3 doesn’t respond to that empty data frame. The access point decides that it’s not there anymore, and administratively deauthenticates it. The LR3 firmware apparently doesn’t ever try to reauthenticate, and thus needs to be powercycled to get it back on the network.

The hostapd logs (edited for clarity) look like this:

13:57:25 x.x.x.x hostapd: wlan0: AP-STA-DISCONNECTED {LR3_MAC}
13:57:25 x.x.x.x hostapd: wlan0: STA {LR3_MAC} IEEE 802.11: authenticated
13:57:25 x.x.x.x hostapd: wlan0: STA {LR3_MAC} IEEE 802.11: associated (aid 1)
13:57:25 x.x.x.x hostapd: wlan0: AP-STA-CONNECTED {LR3_MAC}
13:57:25 x.x.x.x hostapd: wlan0: STA {LR3_MAC} WPA: pairwise key handshake completed (RSN)
13:58:36 x.x.x.x hostapd: wlan0: AP-STA-DISCONNECTED {LR3_MAC}
13:58:36 x.x.x.x hostapd: wlan0: STA {LR3_MAC} IEEE 802.11: authenticated
13:58:36 x.x.x.x hostapd: wlan0: STA {LR3_MAC} IEEE 802.11: associated (aid 1)
13:58:36 x.x.x.x hostapd: wlan0: AP-STA-CONNECTED {LR3_MAC}
13:58:36 x.x.x.x hostapd: wlan0: STA {LR3_MAC} WPA: pairwise key handshake completed (RSN)
14:04:22 x.x.x.x hostapd: wlan0: AP-STA-DISCONNECTED {LR3_MAC}
14:04:22 x.x.x.x hostapd: wlan0: STA {LR3_MAC} IEEE 802.11: disassociated due to inactivity
14:04:23 x.x.x.x hostapd: wlan0: STA {LR3_MAC} IEEE 802.11: deauthenticated due to inactivity (timer DEAUTH/REMOVE)

And there it is. A tad over five minutes after the LR3 authenticates/associates, the access point kicks it off the network because the LR3 ignored the empty-frame query.

(Side note: the LR3’s association/authentication logic appears to be very broken. When it first connects, it will connect/authenticate/disconnect/reauthenticate at randomly-chosen one/three/five/fifteen minute intervals for awhile … then it will go silent for long periods of time, then start the dance again)

Increasing the timeout from 300 seconds to 3600 seconds (i.e., one hour) solved the problem here. The LR3 will perform the connect/authenticate/disconnect/reauthenticate dance at least once an hour, so the maximum inactivity timer won’t be exceeded.

In OpenWRT, set “max_inactivity” to ‘3600’ in /etc/config/wireless. Regular wireless access points should have a similar setting buried somewhere in the “Advanced” tab.

I’ve passed along these findings to Whisker Support. They thanked me for the information, and say that they will be advising customers with connection issues to tweak the wireless access point with the above settings.

Sadly, there won’t be a firmware patch for the LR3. From the conversation with support:

Whisker: Our engineering team wanted to thank you as well. They said that we have completely overhauled ESP32 Firmware for future models. In the meantime, we will be recommending customers to disable WMN for LR3 units.

Me: I’m glad to hear that the team has rewritten the ESP32 firmware. Are there plans to make it available for the LR3, or will it be only for future models?

Whisker: It will only be for future models.

… so LR3 owners that need stable network connectivity will need to configure their access point as outlined above.

The LR3 controller is an ESP32, and there is an apparently stalled replacement firmware project. The next time I have the LR3 open for cleaning, I might pull the controller board and see if I can pull the firmware from the ESP32. Reverse-engineering can be fun.

1 Comment

Public Service Announcement: Do not use ReShip

eBay’s global shipping program is a disaster. Folks outside the US that buy things from eBay have learned to use US-based reshipping services to receive their stuff in a timely and cost-effective manner.

I’d been using Shipito for well over a decade. Over the past few months, though, I’ve been having problems with packages missing small items. Steve over at Big Mess O’ Wires recommends ReShip, so I decided to try them out.

They seemed okay. Their shipping fees were about 5% cheaper than Shipito, packages were reshipped within 24 hours, and packages were opened and photographed as soon as they were received (which was a major contributing factor to Shipito’s issues).

However, packages that were marked as “delivered” in USPS and UPS tracking systems didn’t show up in my account for several days. That was a bit concerning, but I reckoned that they were just overwhelmed with the amount of inbound packages.

Unfortunately, that turned out to not be the case. Two weeks ago, ReShip received three packages for me on the same day. None were placed in my account. I contacted their online support system, and this is how it went:

The order is not showing in our system as being delivered. USPS scans orders as delivered before they get to the warehouse. They do this due to the volume of packages so they are scanned and bundled up for bulk. USPS currently has over 100 orders backlogged to be delivered to us. We are trying to have this resolved. We are very sorry.

We really apologize for this. USPS holds packages at their facility for longer than they should. We have video evidence we have submitted to USPS as proof they don’t scan packages as delivered so we have actually no idea when they deliver packages. You can also monitor your account or Kindly contact USPS regarding your package.

This didn’t smell right. I asked the (outsourced) customer service representative to please escalate this to ReShip for investigation.

The next day, “Diane M” sent this email:

We have been experiencing issues with USPS not delivering to the correct address and then the driver telling us they have back logged packages at the warehouse (this is frequent and we have had to send staff to collect the backlogged packages). We are trying to work with USPS in hopes they will cooperate.

We were delivered a bunch of packages by our neighbors from USPS so hopefully these packages are in there and will be received soon.

… okay, that’s really not good. I said:

The situation seems to be very alarming. What you’re saying is that ReShip cannot reliably receive packages, and there is no recourse available to the customer as USPS says that it has been delivered but ReShip denies that has taken place.

That’s not good. I moved from Shipito to Reship awhile back because Shipito was having theft issues; if ReShip has a bad relationship with USPS, then it’s hard to trust ReShip to safely forward packages.

Is this problem documented by ReShip anywhere, so that customers are aware that ReShip often does not receive packages sent via USPS?

Specific to my situation: two of the three packages have now been marked as “received” and are in my mailbox. How long should I wait for the other package to appear?

Diane replied the following day with this:

We have had issues in the past with USPS and included this in our FAQ section. We have also raised these issues with USPS directly and issued federal complaints. We don’t determine what is and isn’t delivered unfortunately, although having that ability would resolve these issues. If the package was delivered, it may still be in the process of being received.

Okay. I burn about an hour scouring their website looking for a bit saying “USPS doesn’t like us, but we’re working on it”. Can’t find it anywhere. So I say:

I don’t see any reference to problems with USPS anywhere on your website. Could you please send a link?

What are the options regarding the missing package (USPS #9400111699000025640151)? USPS says that it was delivered on 18 June, but you folks say that you don’t have it.

What is ReShip’s liability and responsibility for packages that the carrier delivered but ReShip cannot locate?

What is the best way to resolve this issue, both now and going forward?

Should I escalate to the USPS postal inspection division for investigation?

Diane then ignores my questions:

When USPS delivers packages, they don’t bring a scanner with them at all. They 0deliver packages then drive away. Any packages that are marked as delivered are not done when the packages are delivered at our warehouse (we have evidence of this by video surveillance which we have provided to USPS on multiple occasions). If a package is not delivered to us, there is nothing we can do. That would be between yourself, the vendor, and the carrier. We can certainly write you letter letting you know we did not receive this package so you can submit that to the carrier for a claim.

Right. That’s really not okay with me. The missing package contains an obsolete and somewhat-hard-to-find Apple ][ video card, and I’m not going to tell the guy I bought it from that I didn’t receive it so he needs to refund my money because it isn’t even remotely his fault.

I filed an investigation claim with USPS (I was actually trying to get the postal inspectors directly involved, but it looks like I can’t skip directly to that part).

I looked ReShip up on the Better Business Bureau website (link goes directly to ReShip’s profile) … and, um, wow. They have an “F” rating. The reviews are brutal. They don’t even have a state business license. I sure wish I had checked these reviews before I trusted them with my packages.

I opened a case with the BBB requesting that ReShip reimburse me for the package that they can’t find.

I then told ReShip what I’m doing:

Thank you for your reply.

I’m sorry, but this situation is unacceptable.

Here is what is going to happen:

I have asked USPS to open an investigation into package XXXXX (service request #YYYY). ReShip will be contacted by a postal inspector in the near future. With a bit of luck, that will help to solve your issues with USPS.

I have opened a case with the Portland BBB, case number ZZZZ. I have provided them with this entire email thread. I have asked them to seek USD$85.00 from ReShip as repayment for the package that ReShip has lost.

I will be writing an article about this fiasco on my blog today. With an additional bit of luck, making this situation public can prevent others from using ReShip in the future.

I don’t believe ReShip’s explanation of the situation, but that doesn’t matter — at the end of the day, no matter what the actual reason is, I still won’t have that old 80-column card.

So there it is. Maybe somebody someday will be googling around for reshipping services, see this blog entry, and decide against using ReShip. If this blog entry can prevent just one person from having issues with ReShip, then this fiasco will have at least a minimally positive outcome.

Leave a comment

Franklin ACE 1000 keyboard EPROM dump

A fellow on the Vintage Computer Federation forum needed the EPROM image for a Franklin ACE 1000 keyboard.

It doesn’t look like anyone has dumped it before, so I desoldered the EPROM from the keyboard and dumped the image. It’s an Intel 2758, but it is pin-compatible with the 2716 as what would be A10 on a 2716 is grounded on the keyboard PCB.

The EPROM image is here.

Posted in Franklin | Leave a comment

Franklin ACE 1000 emulation added to MAME

Over the past few months, I’ve been refurbishing a pair of Franklin ACE 1000s. I plan to write a series of articles documenting the things I’ve learned along the way; despite the popularity of these Apple ][+ clones in the 80’s, very little hardware documentation appears to have survived.

One of the things I did to help the repair process was to add Franklin ACE 1000 emulation to MAME. The pull request was merged this morning (https://github.com/mamedev/mame/commit/c471404e026bfa42c016cbcc52b66b77c5b14e39), so it will be in the next release of MAME.

The ROM set is available at https://www.disavowed.jp/hardware/ace1000/ace1000.zip. This set contains the real Franklin character ROM, which doesn’t appear to be available anywhere else.

Enjoy 🙂

Posted in Franklin | Leave a comment

Notice: LineageOS build repository discontinued.

Awhile back, I mentioned that my bandwidth was being consumed by a few bad actors out there who are scraping the entire LineageOS build repository.

This is still happening. It’s been especially bad over the past week.

I’ve been null-routing entire networks in an attempt to keep the service running while preventing jerks from hoovering the entire repo. It’s turned into a game of whack-a-mole, and honestly, providing this service isn’t worth the cycles I’m burning keeping things running for an indifferent “community”.

As of today, the LineageOS build service has been discontinued.

My build script is at https://www.disavowed.jp/lineageos/build-lineage.sh for those who need security updates for their devices.

I’m very sorry to have to do this. I’m especially sorry towards the eight people who have donated over the past few years to support this service. This is why humans can’t have nice things.

Posted in LineageOS | 11 Comments

LineageOS sustaining build repository moved to lineageos.rezrov.net

Multiple people have pinged me regarding lineageos.disavowed.jp having issues.

lineageos.disavowed.jp was deprecated several months ago in favor of lineageos.rezrov.net and the SSL certificate for the old domain finally expired.

I’ve therefore removed the HTTPS redirect to lineageos.rezrov.net with a simple HTTP redirect (because, natch, there won’t be a valid SSL cert for the redirect anymore).

Again: lineageos.disavowed.jp is dead. Use lineageos.rezrov.net.

Thank you.

Posted in LineageOS | Leave a comment

A sane Octoprint (octopi) USB camera daemon

Octoprint is neat. However, the USB/webcamera support is a bit obtuse — especially when you throw haproxy into the mix.

The Octoprint documentation recommends using mjpg-streamer as a standalone daemon to convert a v4l video stream into a HTTP stream … and use haproxy to selectively redirect traffic to that stream when an arbitrary value prepends the HTTP URI.

There are a few issues:

  • The recommended haproxy.cfg isn’t compatible with current versions of haproxy,
  • Octoprint appends a seemingly-random session ID to the camera URI, which confuses the hell out of mjpg-streamer,
  • mjpg-streamer doesn’t appear to handle multiple simultaneous streams, resulting in the infuriating “403: Forbidden! frame already sent” error,
  • mjpg-streamer itself is complete overkill here.

Wanting this to work, I looked around for a simpler scheme. I came across Igor Maculan’s “Simple Python Motion Jpeg” daemon (https://gist.github.com/n3wtron/4624820), which looked promising.

I spent a few hours this morning porting it to python 3.x, fixing a few bugs, and adding command-line tunables. It works, and it works well. It is available on GitHub at https://github.com/christopherkobayashi/octoprint-stuff/blob/main/webcam.py

Below is a working haproxy.cfg that handles SSL:

global
	maxconn		20000
	log		127.0.0.1 local0
	user		haproxy
	chroot		/usr/share/haproxy
	pidfile		/run/haproxy.pid
	daemon

defaults 
	timeout		connect 5s
	timeout		client 1m
	timeout		server 1m

frontend public_ssl
	bind		:::443 v4v6 ssl crt /etc/letsencrypt/live/both.pem
	use_backend	webcam if { path_beg /webcam/ }
	default_backend	octoprint

backend octoprint
	mode		http
	http-request	replace-uri '^([^\ :]*)\ /(.*)' '\1 /\2'
	option		forwardfor
	server		octoprint1 127.0.0.1:5000

backend webcam
	mode		http
	http-request	replace-uri '^([^\ :]*)\/webcam/(.*)$' '\1/\2'
        server webcam	127.0.0.1:8080

The Octoprint web camera URL should be “https://${SERVER_NAME}/webcam/${SOMETHING}.mjpg”. ${SOMETHING}.mjpg can be anything, actually … webcam.py will respond to any request with a MJPEG stream.

I hope this saves time for others banging their heads against Octoprint’s … interesting camera support scheme.

Leave a comment