{"id":13830393,"url":"https://github.com/mecparts/RetroWiFiModem","last_synced_at":"2025-07-09T11:32:53.487Z","repository":{"id":133949337,"uuid":"258904677","full_name":"mecparts/RetroWiFiModem","owner":"mecparts","description":"An ESP8266 based RS232 \u003c-\u003e WiFi modem with Hayes AT style commands and LED indicators","archived":false,"fork":false,"pushed_at":"2024-08-29T01:50:20.000Z","size":3430,"stargazers_count":152,"open_issues_count":0,"forks_count":25,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-08-29T02:54:59.745Z","etag":null,"topics":["esp8266","hayes","kicad","modem","openscad","retrocomputing","rs-232","rs232","vintage","wifi"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mecparts.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-26T00:40:27.000Z","updated_at":"2024-08-29T01:50:23.000Z","dependencies_parsed_at":"2024-01-13T15:37:54.780Z","dependency_job_id":"67c68a8f-c5b0-4635-bab5-751cf8c847b1","html_url":"https://github.com/mecparts/RetroWiFiModem","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mecparts%2FRetroWiFiModem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mecparts%2FRetroWiFiModem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mecparts%2FRetroWiFiModem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mecparts%2FRetroWiFiModem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mecparts","download_url":"https://codeload.github.com/mecparts/RetroWiFiModem/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225539385,"owners_count":17485317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esp8266","hayes","kicad","modem","openscad","retrocomputing","rs-232","rs232","vintage","wifi"],"created_at":"2024-08-04T10:00:59.453Z","updated_at":"2024-11-20T11:30:43.019Z","avatar_url":"https://github.com/mecparts.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# Retro WiFi modem\n\n## An ESP8266 based RS232 \\\u003c-\\\u003e WiFi modem with Hayes AT style commands and LED indicators\n\n### (And yes, this version makes the noises)\n\n![Front Panel](images/Front%20Panel.jpg \"Front Panel\")\n\nThis project grew out of a desire to get an old Ampro LB+/Z80 hooked up\nto the Internet.\n\nRight from the start, I knew I wanted a row of LED indicators at the\nfront of the modem so that it would be reminiscent of an old Hayes\nSmartmodem. (I briefly considered finding an old Smartmodem on eBay, but\nsoon remembered that the case had in fact been made of metal; they don't\nbuild 'em like that anymore.)\n\nSince the modem was going to be hooked up to the Little Board's\nserial port, I needed an actual RS-232 level serial port, with either a\nDB-25 or DE-9 connector.\n\nAnd finally, since I wanted the Hayes style LEDs, I thought it would be\nhandy to have the Hayes AT commands too, at least as close as I could\nmanage.\n\nThat was all I started with. I couldn't tell you how I stumbled across\nthe whole WiFi modem thing; I can't even remember what terms I searched\nwith but very quickly I came across the message thread at [WiFi232's\nEvil\nClone](http://www.vcfed.org/forum/entry.php?740-WiFi232-s-Evil-Clone\u0026bt=1056).\nInspired by that, and [Paul Rickards'\nWiFi232](http://biosrhythm.com/?page_id=1453), and [Daniel Jameson's\nESP8266 based virtual modem](https://github.com/stardot/esp8266_modem) I\ngot started.\n\nI had a preliminary version put together and working by the first\nevening. Then the wholesale changes to the software began. And for the\nlongest time, it looked like they'd never end. Eventually though, they\ncalmed down and \"wholesale changes\" downshifted to \"another tweak I'd\nlike to make.\"\n\nThe hardware didn't change nearly as much from beginning to end. I did\nthe development on a Wemos D1 R1 and a little half length solderless\nbreadboard mounted together. The plan for the final hardware was always\nto use a [Wemos D1 mini](https://docs.wemos.cc/en/latest/d1/d1_mini.html).\nA MAX3237 took care of the 3.3V \u003c-\u003e RS-232 level shifting, and a\n74HCT245 was used to drive the indicator LEDs.\n\n![Prototype](images/Prototype.jpg \"Prototype\")\n\nThe only major additions to the hardware during development was an OR\ngate on the serial output from the ESP8266 and the addition of a\nDFPlayer Mini for the dialing and connection sounds.\n\nOn startup, the ESP8266 sends out some debug information\n(at an oddball baud rate) through the serial port. It shows up as\ngarbage characters to whatever's hooked up to the serial port. It\nannoyed me enough that I fed the Tx signal through the OR gate, with the\nother input hooked up to an output pin that I could count on remaining\nhigh (thereby masking off the Tx signal) until after the sketch had\nstarted and set it low.\n\nAnd while it didn't make the cut the first time around, there's a\nDFPlayer Mini in this version for faux dialing and connection sounds.\nThey really do complete the whole retro feel (but they can be turned off\ntoo).\n\n## The Hardware\n\n![Interior](images/Interior.jpg \"Interior\")\n\nThe second time around, I decided that I was going to bite the bullet\nand go with some surface mount stuff, starting with the MAX3237. Having\na full suite of RS-232 control signals seemed worth it. I stuck with\nthrough hole components where I could (I already had most of them in my\nparts box) but adding the DFPlayer Mini meant that the 74HC32 and\n74HCT245 had to be surface mount just to make them fit.\n\nIn keeping with the retro theme, the modem uses classic Hayes style\nblinking LEDs and a DE-9F for the RS-232 connector. Everything is\ndisplayed and brought out to the DE-9F connector: RTS, CTS, DSR, DTR,\nDCD, RI, TxD and RxD.\n\nThe PCB is laid out for a\n[Wemos D1 mini](https://docs.wemos.cc/en/latest/d1/d1_mini.html) and the\nsoftware expects to see just that. If you're just using the software and\nnot the PCB, there's no reason you couldn't use another kind of ESP8266\nboard; I used a D1 R1 myself when I was developing the modem. You'd just\nneed to add pin definitions for your board in RetroWiFiModem.h.\n\nA separate 3.3V regulator is used to power the MAX3232 IC and 74HC32\nquad OR gate. Some (most?) D1 mini clones have the smallest 3.3V\nregulator on board that they can get away with to power the board, and\nthey don't have a lot of mA's left over to power anything else. Better\nsafe than sorry.\n\n![Back Panel](images/Back%20panel.jpg \"Back Panel\")\n\nThe power connector expects a 2.1mm I.D. x 5.5mm O.D. barrel plug,\ndelivering 5 volts, centre positive.  I used a Tri-Mag L6R06H-050 (5V,\n1.2A), [DigiKey part#\n364-1251-ND](https://www.digikey.com/product-detail/en/tri-mag-llc/L6R06H-050/364-1251-ND/7682614).\nIf you plug in a 9V adapter like you'd use for an Arduino, you *will*\nlet the magic smoke out and have an ex-modem on your hands.\n\n![Schematic](images/RetroWiFiModem.sch.png \"Schematic\")\n\nOn the off chance that there's someone else out there with a well\nstocked parts box and a burning desire to put together their own WiFi\nmodem, there's a [BOM](kicad/RetroWiFiModem-bom.csv) in the kicad\nsub directory. If you actually had to go out and buy all the parts, it\nreally wouldn't be cost effective.\n\nThen again, how practical is getting an Ampro Little Board on the\nInternet? Practicality isn't always everything. Sometimes nostalgia is\nworth the effort.\n\n## The case\n\nLike I said at the start, I would have loved to have used an old Hayes\nSmartmodem case, but they were metal and wouldn't have allowed the WiFi\nto work particularly well.\n\nIn the end I went with a Hammond 1593N case (DigiKey part #\n[HM963-ND](https://www.digikey.com/en/products/detail/hammond-manufacturing/1593NBK/1090774)\nor [HM964-ND](https://www.digikey.com/en/products/detail/hammond-manufacturing/1593NGY/1090775)\ndepending on whether you like black or grey). STL and OpenSCAD\nfiles are included for the front and back panels. You could use the\nproper Hammond red panel for the front (DigiKey part #\n[HM965-ND](https://www.digikey.com/en/products/detail/hammond-manufacturing/1593NIR10/1090776)),\n*but* they're only available in 10 packs and their price is highway robbery.\nI ended up using a slightly smaller red panel (DigiKey part #\n[HM889-ND](https://www.digikey.com/en/products/detail/hammond-manufacturing/1593SIR10/409899))\nthat was ~much~ cheaper (it has recently increased in price by 500%)\nand available in single units.\n\nThe labels are unbelievably low tech. I print them on a piece of inkjet\ntransparency film. I then cut that down to size so that it will fit\nunder the LED opening. Then I attach the trimmed down transparency piece\nto a length of matte finish, invisible tape and carefully position it in\nplace. A bit of careful work with an x-acto knife and you've got\nyourself a label that looks like it's part of the panel. If you look\nclosely at the front panel image you can see the edges of the\ntransparency film and the tape, but in practice they both essentially\ndisappear.\n\n## The PCB\n\nThe PCB includes cutouts for the two columns that join the case\ntogether, and mounting holes for the 6 standoffs. Also, there's an oddly\nshaped cutout in back end to allow a particular IDC DE-9F I had on hand.\nIt's available from DigiKey (or a very close clone is) but it's fairly\npricey. But there's plenty of room for an ordinary solder cup DE-9F.\nYou'd most likely want to omit the 10 pin header and just wire the DE-9F\nright to the board.\n\n## The Software\n\nIn a nod to its popularity, the command set I used largely follows that\nused in [Paul Rickards' WiFi232](http://biosrhythm.com/?page_id=1453)\nmodem. Even if the innards are completely different, it made sense to\nmake it *work* like what people were already used to. There's a reason\neveryone's been copying the Hayes command set for almost 40 years!\n\n### First time setup\n\nThe default serial configuration is 9600bps, 8 data bits, no parity, 1\nstop bit.\n\nHere's the commands you need to set up the modem to automatically\nconnect to your WiFi network:\n\n1. `AT$SSID=your WiFi network name` to set the WiFi network that the\nmodem will connect to when it powers up.\n2. `AT$PASS=your WiFi network password` to set the password for the\nnetwork.\n3. `ATC1` to connect to the network.\n4. Optional stuff:\n   * `AT$SB=speed` to set the default serial speed.\n   * `AT$SU=dps` to set the data bits, parity and stop bits.\n   * `ATNETn` to select whether or not to use Telnet protocol.\n   * `AT\u0026Kn` to use RTS/CTS flow control or not.\n   * `AT\u0026Dn` to set up DTR handling.\n5. `AT\u0026W` to save the settings.\n\nOnce you've done that, the modem will automatically connect to your WiFi\nnetwork on power up and will be ready to \"dial up\" a connection with\nATDT.\n\n### Command Reference\n\nMultiple AT commands can be typed in on a single line. Spaces between\ncommands are allowed, but not within commands (i.e. AT S0=1 X1 Q0 is\nfine; ATS 0=  1 is not). Commands that take a string as an argument\n(e.g. AT$SSID=, AT$TTY=) assume that *everything* that follows is a part\nof the string, so no commands are allowed after them.\n\nCommand | Details\n------- | -------\n+++     | Online escape code. Once your modem is connected to another device, the only command it recognises is an escape code of a one second pause followed by three typed plus signs and another one second pause, which puts the modem back into local command mode. The character used can be set with `ATS2=n`.\nA/      | Repeats the last command entered. Do not type AT or press Enter.\nAT      | The attention prefix that precedes all command except A/ and +++.\nAT?     | Displays a help cheatsheet.\nATA     | Force the modem to answer an incoming connection when the conditions for auto answer have not been satisfied.\nATC?\u003cbr\u003eATC*n* | Query or change the current WiFi connection status. A result of 0 means that the modem is not connected to WiFi, 1 means the modem is connected. The command ATC0 disconnects the modem from a WiFi connection. ATC1 connects the modem to the WiFi.\nATDS*n* | Calls the host specified in speed dial slot *n* (0-9).\nATDT\u003ci\u003e[+=-]host[:port]\u003c/i\u003e | Tries to establish a WiFi TCP connection to the specified host name or IP address. If no port number is given, 23 (Telnet) is assumed. You can also use ATDT to dial one of the speed dial slots in one of two ways:\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003eThe alias in each speed dial slot is checked to see if it matches the specified hostname.\u003c/li\u003e\u003cli\u003eA host specified as 7 identical digits dials the slot indicated by the digit. (i.e. 2222222 would speed dial the host in slot 2).\u003c/li\u003e\u003c/ul\u003ePreceding the host name or IP address with a +, = or - character overrides the ATNET setting for the period of the connection.\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003e**+** forces NET2 (fake Telnet)\u003c/li\u003e\u003cli\u003e**=** forces NET1 (real Telnet)\u003c/li\u003e\u003cli\u003e**-** forces NET0 (no Telnet)\u003c/li\u003e\u003c/ul\u003eOnce the dial attempt has begun, pressing any key before the connection is established will abort the attempt.\nATE?\u003cbr\u003eATE*n* | Command mode echo. Enables or disables the display of your typed commands.\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003eE0 Command mode echo OFF. Your typing will not appear on the screen.\u003c/li\u003e\u003cli\u003eE1 Command mode echo ON. Your typing will appear on the screen.\u003c/li\u003e\u003c/ul\u003e\nATGET*http\u0026#58;//host[/page]* | Displays the contents of a website page. **https** connections are not supported. Once the contents have been displayed, the connection will automatically terminate.\nATH | Hangs up (ends) the current connection.\nATI | Displays the current network status, including sketch build date, WiFi and call connection state, SSID name, IP address, and bytes transferred.\nATL?\u003cbr\u003eATL*n* | Query or set the volume of the speaker (0-3).\nATM?\u003cbr\u003eATM*n* | Query or set whether the speaker is enabled or disabled. ATM0 disables the speaker. ATM1 enables it.\nATNET?\u003cbr\u003eATNET*n* | Query or change whether telnet protocol is enabled. A result of 0 means that telnet protocol is disabled; 1 is *Real* telnet protocol and 2 is *Fake* telnet protocol. If you are connecting to a telnet server, it may expect the modem to respond to various telnet commands, such as terminal name (set with `AT$TTY`), terminal window size (set with `AT$TTS`) or terminal speed. Telnet protocol should be enabled for these sites, or you will at best see occasional garbage characters on your screen, or at worst the connection may fail.\u003cbr\u003e\u003cbr\u003eThe difference between *real* and *fake* telnet protocol is this: with *real* telnet protocol, a carriage return (CR) character being sent from the modem to the telnet server always has a NUL character added after it. The implementation of the telnet protocol used by some BBSes doesn't properly strip out the NUL character. When connecting to such BBSes (Particles! is one), use *fake* telnet.\u003cbr\u003e\u003cbr\u003eWhen using *real* telnet protocol, when the telnet server sends a CR character followed by a NUL character, only the CR character will be sent to the serial port; the NUL character will be silently stripped out. With *fake* telnet protocol, the NUL will be passed through.\nATO | Return online. Use with the escape code (+++) to toggle between command and online modes.\nATQ?\u003cbr\u003eATQ*n* | Enable or disable the display of result codes. The default is Q0.\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003eQ0 Display result codes.\u003c/li\u003e\u003cli\u003eQ1 Suppress result codes (quiet).\u003c/li\u003e\u003c/ul\u003e\nATRD\u003cbr\u003eATRT | Displays the current UTC date and time from NIST in the format *YY-MM-DD HH:MM:SS*. A WiFi connection is required and you cannot be connected to another site.\nATS0?\u003cbr\u003eATS0=*n* | Display or set the number of \"rings\" before answering an incoming connection. Setting `S0=0` means \"don't answer\".\nATS2?\u003cbr\u003eATS2=*n* | Display or set the ASCII code used in the online escape sequence. The default value is 43 (the + plus character). Setting it to any value between 128 and 255 will disable the online escape function.\nATV?\u003cbr\u003eATV*n* | Display result codes in words or numbers. The default is V1.\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003eV0 Display result codes in numeric form.\u003c/li\u003e\u003cli\u003eV1 Display result codes in text form.\u003c/li\u003e\u003c/ul\u003e\nATX?\u003cbr\u003eATX*n* | Control the amount of information displayed in the result codes. The default is X1 (extended codes).\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003eX0 Display basic codes (CONNECT, NO CARRIER)\u003c/li\u003e\u003cli\u003eX1 Display extended codes (CONNECT speed, NO CARRIER (connect time))\u003c/li\u003e\u003c/ul\u003e\nATZ | Resets the modem.\nAT\u0026F | Reset the NVRAM contents and current settings to the sketch defaults. All settings, including SSID name, password and speed dial slots are affected.\nAT\u0026D?\u003cbr\u003eAT\u0026D*n* | Display or set the handling of DTR going inactive. The default is \u0026D0 (ignored).\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003e\u0026D0 Ignore\u003c/li\u003e\u003cli\u003e\u0026D1 Go to command mode\u003c/li\u003e\u003cli\u003e\u0026D2 End call\u003c/li\u003e\u003cli\u003e\u0026D3 Reset modem\u003c/li\u003e\u003c/ul\u003e\nAT\u0026K?\u003cbr\u003eAT\u0026K*n* | Data flow control. Prevents the modem's buffers for received and transmitted from overflowing.\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003e\u0026K0 Disable data flow control.\u003c/li\u003e\u003cli\u003e\u0026K1 Use hardware flow control. Requires that your computer and software support Clear to Send (CTS) and Request to Send (RTS) at the RS-232 interface.\u003c/li\u003e\u003c/ul\u003e\nAT\u0026R?\u003cbr\u003eAT\u0026R=*server pwd* | Query or change the password for incoming connections. If set, the user has 3 chances in 60 seconds to enter the correct password or the modem will end the connection.\nAT\u0026V*n* | Display current or stored settings.\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003e\u0026V0 Display current settings.\u003c/li\u003e\u003cli\u003e\u0026V1 Display stored settings.\u003c/li\u003e\u003c/ul\u003e\nAT\u0026W | Save current settings to NVRAM.\nAT\u0026Zn?\u003cbr\u003eAT\u0026Z*n*=*host[:port],alias* | Store up to 10 numbers in NVRAM, where *n* is the position 0-9 in NVRAM, and *host[:port]* is the host string, and *alias* is the speed dial alias name. The host string may be up to 50 characters long, and the alias string may be up to 16 characters long.\u003cbr\u003e\u003cbr\u003eExample: `AT\u0026Z2=particlesbbs.dyndns.org:6400,particles`\u003cbr\u003e\u003cbr\u003eThis number can then be dialed in any of the following ways:\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003e`ATDS2`\u003c/li\u003e\u003cli\u003e`ATDTparticles`\u003c/li\u003e\u003cli\u003e`ATDT2222222`\u003c/li\u003e\u003c/ul\u003e\nAT$AE?\u003cbr\u003eAT$AE=*startup AT cmd* | Query or change the command line to be executed when the modem starts up.\nAT$AYT | Sends a Telnet \"Are You There?\" command if connected to a Telnet remote.\nAT$BM?\u003cbr\u003eAT$BM=*server busy msg* | Query or change a message to be returned to an incoming connection if the modem is busy (i.e. already has a connection established).\nAT$MDNS\u003cbr\u003eAT$MDNS=*mDNS name* | Query or change the mDNS network name (defaults to \"espmodem\"). When a non zero TCP port is defined, you can telnet to that port with **telnet mdnsname.local port**.\nAT$PASS?\u003cbr\u003eAT$PASS=*WiFi pwd* | Query or change the current WiFi password. The password is case sensitive. Clear the password by issuing the set command with no password. The maximum length of the password is 64 characters.\nAT$SB?\u003cbr\u003eAT$SB=*n* | Query or change the current baud rate. Valid values for \"n\" are 110, 300, 450, 600, 710, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 76800 and 115200. Any other value will return an ERROR message. The default baud rate is 1200. The Retro WiFi modem does not automatically detect baud rate like a dial-up modem. The baud rate setting must match that of your terminal to operate properly. It will display garbage in your terminal otherwise.\nAT$SP?\u003cbr\u003eAT$SP=*n* | TCP server port to listen on. A value of 0 means that the TCP server is disabled, and no incoming connections are allowed.\nAT$SSID?\u003cbr\u003eAT$SSID=*ssid name* | Query or change the current SSID to the specified name. The given SSID name is case sensitive. Clear the SSID by issuing the set command with no SSID. The maximum length of the SSID name is 32 characters.\nAT$SU?\u003cbr\u003eAT$SU=*dps* | Query or change the current number of data bits ('d'), parity ('p') and stop bits ('s\") of the serial UART. Valid values for 'd' are 5, 6, 7 or 8 bits. Valid values for 'p' are (N)one, (O)dd or (E)ven parity. Valid values for 's' are 1 or 2 bits. The default settings are 8N1. The UART setting must match your terminal to work properly.\nAT$TTL?\u003cbr\u003eAT$TTL=*telnet location* | Query or change the Telnet location value to be returned when the Telnet server issues a SEND-LOCATION request. The default value is \"Computer Room\".\nAT$TTS?\u003cbr\u003eAT$TTS=*WxH* | Query or change the window size (columns x rows) to be returned when the Telnet server issues a NAWS (Negotiate About Window Size) request. The default value is 80x24. For terminals that are smaller than 80x24, setting these values appropriately will enable paging on the help (AT?) and network status (ATI) commands.\nAT$TTY?\u003cbr\u003eAT$TTY=*terminal type* | Query or change the terminal type to be returned when the Telnet server issues a TERMINAL-TYPE request. The default value is \"ansi\".\nAT$W?\u003cbr\u003eAT$W=*n* | Startup wait.\u003cbr\u003e\u003cbr\u003e\u003cul\u003e\u003cli\u003e$W=0 Startup with no wait.\u003c/li\u003e\u003cli\u003e$W=1 Wait for the return key to be pressed at startup.\u003c/li\u003e\u003c/ul\u003e\n\n### Updating the Software\n\nWhile I liked the idea of being able to update the software OTA, it\nseemed to make more sense in my situation to be able to *push* a new\nversion as I built it rather than have the modem *pull* it. So that's\nwhat I did. It uses the default OTA upload capability built into the\nArduino IDE.\n\n**Jan 24/22:** It's been reported that the ESP8266 core is slightly\nsnafu'd at the moment, and that it's breaking things in the modem\nsoftware. As a workaround, I've added the bin file that gets uploaded\nto the modem in the repository. I haven't updated my ESP8266 core in\nages; \"if it isn't broken, don't break it\", and everything still works\nfor me. The bin file can be uploaded with the *espota.py* tool in the\nESP8266 tool directory tree.\n\n(If TPTB have deleted/renamed/moved that tool in the current core,\nyou'll have to figure out how to do a manual OTA update.)\n\n### RTS/CTS handshaking and a dead spin loop issue\n\nSomething I noticed with ESP8266 software that puzzled me was the\nnumber of places I saw a series of Serial print statements being broken\nup with calls to yield(), like so:\n\n```\n   Serial.print(\"Hello world!\\n\");\n   yield();\n   Serial.print(\"How are you today?\\n\");\n   yield();\n```\nIt didn't take long to figure out what was going on; The print() call\nwas blocking, and at lower baud rates, even printing a few relatively\nshort strings was enough to cause the watchdog to bark and cause a\nreset. So the repetitive yield() calls were an attempt to feed the\nwatchdog often enough to keep it from barking.\n\nWhat does this have to do with RTS/CTS handshaking? Simply put,\nlowering RTS for more than a few seconds was causing the watchdog to\nbark as well. So I started digging.\n\nIn cores/esp8266/uart.cpp I found the following function:\n\n```\nstatic void\nuart_do_write_char(const int uart_nr, char c)\n{\n    while(uart_tx_fifo_full(uart_nr));\n\n    USF(uart_nr) = c;\n}\n```\n\nThis is the low level function that everything calls to send a character\nout the serial port. The cause of the watchdog barking is in the dead\nspin while loop. It waits until there's room in the transmit FIFO to add\nanother character. So if RTS/CTS handshaking is enabled, and RTS is low\nfor longer than the watchdog likes: woof.\n\nWhat I did to quiet the watchdog down both when sending long strings at\nlow baud rates and during long waits for RTS to come active again was to\nadd a yield() call to the dead spin while loop, like so:\n\n```\nstatic void\nuart_do_write_char(const int uart_nr, char c)\n{\n    while(uart_tx_fifo_full(uart_nr))\n      yield();\n\n    USF(uart_nr) = c;\n}\n```\n\nThis way, no matter how long the code has to wait for space in the\ntransmit FIFO, the watchdog is kept well fed and quiet.\n\n## Status\n\nAs I said way back in 2020, is a personal project like this ever\n*really* finished? I've had two units assembled and in use since the\nspring of 2020, and a third since 2022, and while there's\nbeen some software changes since then, and a second rev of the hardware\nto bring out all the RS-232 control signals and add in the faux dialing\nand connections sounds, I really don't expect any more changes. But I've\nsaid that before! There are no outstanding bugs that I'm aware of, and\nno new features on my wish list. For the time being at least, I think\nit's complete.\n\n### Linux, Telnet, Zmodem and downloading binary files\n\nHave you used the modem to 'dial' into a Linux box? And have you done a\n`sz binary_file` on the Linux box? And at a completely reproducible\npoint in the file, has the connection dropped? But other binary files\nwork just fine? Then read on.\n\nThis drove me slightly batty for months. I finally narrowed it down to\ntrying to send blocks of binary data with a large number of FF bytes. I\neventually created a test file consisting of 2K of FF and used that to\ntest with. I could download it through the modem with Xmodem just fine.\nYmodem also worked if I kept the block size down to 128 bytes - but the\nconnection would drop instantly if I tried sending 1K blocks. Same thing\nwith Zmodem.\n\nIn fact, if I just tried `cat binary_file`, the connection would\ndrop. Which eventually got me thinking. Sitting at the console on my\nmain Linux box, I telnet'd to the same box and logged in. No WiFi modem\ninvolved anywhere, just a telnet session on the console to the same box.\nI then did a `cat binary_file`. The telnet connection dropped, and I\nwas back in my original session.\n\nIt's the Linux telnet daemon. Not the modem at all.\n\nTo prove it to myself, I hooked up WiFi modems to two systems on their\nserial ports and had one dial into the other. I could send the all FF\nbinary file back and forth with Zmodem and Ymodem, no trouble at all.\n\nBut you really, really need to download that binary file through the\nmodem from a telnet connection to a Linux box? You're not going to be\nable to use Zmodem. Ymodem will work (the sy command defaults to 128\nbyte blocks), as will Xmodem. But not Zmodem.\n\nOddly enough, the telnet daemon has no trouble *receiving* the all FF\nbinary file. Only sending it. Your guess as to why is probably better\nthan mine.\n\n## References\n\n* [WiFi232 - An Internet Hayes Modem for your Retro Computer](http://biosrhythm.com/?page_id=1453)\u003cbr\u003e\n* [WiFi232's Evil Clone](https://forum.vcfed.org/index.php?threads/wifi232s-evil-clone.1070412/)\u003cbr\u003e\n* [Jussi Salin's Virtual modem for ESP8266](https://github.com/jsalin/esp8266_modem)\u003cbr\u003e\n* [Stardot's ESP8266 based virtual modem](https://github.com/stardot/esp8266_modem)\u003cbr\u003e\n* [Roland Juno's ESP8266 based virtual modem](https://github.com/RolandJuno/esp8266_modem)\n\n## Acknowledgements\n\n* A whole lot of people owe a big vote of thanks to Jussi Salin for\nreleasing their virtual modem code for the ESP8266 and starting the\nball rolling.\n* Paul Rickards for an amazing bit of hardware to draw inspiration from.\n* All the Stardot contributors for their work.\n* And, of course, Dennis C. Hayes for creating something so simple and\nelegant that has stood the test of time.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmecparts%2FRetroWiFiModem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmecparts%2FRetroWiFiModem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmecparts%2FRetroWiFiModem/lists"}