├── LICENSE.txt ├── README.md ├── case ├── .gitignore ├── back_panel.scad ├── back_panel.stl ├── front_panel.ods ├── front_panel.pdf ├── front_panel.scad └── front_panel.stl ├── images ├── Back panel.jpg ├── Builtin help.png ├── Front panel.jpg ├── Interior.jpg ├── PicoWifiModem.sch.png └── Prototype.jpg ├── kicad ├── .gitignore ├── Pico_Wifi_modem-bom.csv ├── Pico_Wifi_modem.kicad_pcb ├── Pico_Wifi_modem.net ├── Pico_Wifi_modem.pro ├── Pico_Wifi_modem.sch ├── fp-info-cache ├── fp-lib-table ├── gerbers │ ├── Pico_Wifi_modem-B.Cu.gbl │ ├── Pico_Wifi_modem-B.Mask.gbs │ ├── Pico_Wifi_modem-B.Paste.gbp │ ├── Pico_Wifi_modem-B.SilkS.gbo │ ├── Pico_Wifi_modem-Edge.Cuts.gm1 │ ├── Pico_Wifi_modem-F.Cu.gtl │ ├── Pico_Wifi_modem-F.Mask.gts │ ├── Pico_Wifi_modem-F.Paste.gtp │ ├── Pico_Wifi_modem-F.SilkS.gto │ ├── Pico_Wifi_modem-NPTH-drl_map.gbr │ ├── Pico_Wifi_modem-NPTH.drl │ ├── Pico_Wifi_modem-drl_map.gbr │ ├── Pico_Wifi_modem.drl │ └── Pico_Wifi_modem.zip ├── library │ └── Pico_Wifi_modem.lib ├── modules.pretty │ ├── BARREL_JACK.kicad_mod │ ├── C_Disc_D3_P2.5.kicad_mod │ ├── C_Disc_D3_P5.kicad_mod │ ├── DIP-20_W7.62mm_LongPads.kicad_mod │ ├── DIP-8_W7.62mm_LongPads.kicad_mod │ ├── Diode_DO-41_SOD81_Horizontal_RM10.kicad_mod │ ├── IDC_Header_Straight_10pins.kicad_mod │ ├── LED-3MM.kicad_mod │ ├── MountingHole_3.2mm_Hammond_1593.kicad_mod │ ├── R3.kicad_mod │ ├── RPi_PicoW.kicad_mod │ ├── SOIC-28W_7.5x17.9mm_Pitch1.27mm.kicad_mod │ └── TO-92_Inline_Narrow_Oval.kicad_mod └── sym-lib-table └── src ├── CMakeLists.txt ├── at_basic.h ├── at_extended.h ├── at_proprietary.h ├── build └── .gitignore ├── eeprom.h ├── globals.h ├── lwipopts.h ├── support.h ├── tcp_support.h ├── wifi_modem.cpp └── wifi_modem.h /README.md: -------------------------------------------------------------------------------- 1 | # Pico WiFi modem 2 | 3 | ## A Pico W based RS232 \<-\> WiFi modem with Hayes AT style commands and LED indicators 4 | 5 | | ![Front Panel](images/Front%20panel.jpg "Front Panel") | 6 | |:--:| 7 | | The Pico WiFi modem | 8 | 9 | This project began as an exercise to learn about the Pico W and lwIP. 10 | Then, as I figured things out, it sort of took on a life of its own... 11 | 12 | The code was ported from my 13 | [Retro WiFi Modem](https://github.com/mecparts/RetroWiFiModem). 14 | One look at it will betray its Arduino IDE origin! It's definitely not 15 | the most efficient way to do things in the Pico world, but it worked 16 | well enough for my purposes in learning "okay, I know what I want to do 17 | here, but how does the Pico C/C++ SDK do it?" 18 | 19 | It likely would have been much faster to install one of the Pico-Arduino 20 | cores. I imagine there would have been far fewer code changes. But I 21 | don't think I would have learned anywhere near as much about the 22 | workings of the Pico W and lwIP as I did by using the Pico SDK. 23 | 24 | ## The Hardware 25 | 26 | | ![Prototype](images/Prototype.jpg "Prototype") | 27 | |:--:| 28 | | The prototype | 29 | 30 | As with the code, I re-up'd a lot of the original hardware decisions. 31 | But, since this time around it wasn't a pandemic project that I was 32 | trying to do as much as possible with parts on hand, I used a MAX3237 33 | instead of a MAX3232. 34 | 35 | | ![Interior](images/Interior.jpg "Interior") | 36 | |:--:| 37 | | The interior | 38 | 39 | The modem still uses the classic Hayes style blinking LEDs and a DE-9F 40 | for the RS-232 connector. Everything is displayed: RTS, CTS, DSR, DTR, 41 | DCD, RI, TxD and RxD. And this time, since I used a MAX3237, they're all 42 | brought out to the DE-9F connector. So things like using a change in the 43 | DTR line to go to command mode or end a call are supported (on a system 44 | that brings DTR out to the serial port, of course). 45 | 46 | Since the Pico W doesn't have EEPROM on board, I added a small 4K I2C 47 | EEPROM to the mix. I could have used a block of the Pico's flash, but I 48 | wanted to get a feel for I2C on the Pico as well. 49 | 50 | The Pico is socketed on this first board due to the lack of OTA 51 | programming. The PCB is set up to allow it to be soldered directly on 52 | the board once I have that figured out. 53 | 54 | | ![Back Panel](images/Back%20panel.jpg "Back Panel") | 55 | |:--:| 56 | | The back panel | 57 | 58 | The power connector expects a 2.1mm I.D. x 5.5mm O.D. barrel plug, 59 | delivering 5 volts, centre positive. I used a Tri-Mag L6R06H-050 (5V, 60 | 1.2A), [DigiKey part# 364-1251-ND](https://www.digikey.com/product-detail/en/tri-mag-llc/L6R06H-050/364-1251-ND/7682614). 61 | If you plug in a 9V adapter like you'd use for an Arduino, you *will* 62 | let the magic smoke out and have an ex-modem on your hands. 63 | 64 | | ![Schematic](images/PicoWifiModem.sch.png "Schematic") | 65 | |:--:| 66 | | The schematic | 67 | 68 | On the off chance that there's someone else out there with a well 69 | stocked parts box and a burning desire to put together their own Pico 70 | WiFi modem, there's a [BOM](kicad/Pico_WiFi_Modem-bom.csv) in the 71 | kicad sub directory. As was true with the original ESP8266 design, if 72 | you actually had to go out and buy all the parts, it really wouldn't be 73 | cost effective. 74 | 75 | ## The case 76 | 77 | I re-used the same case, a Hammond 1593N case (DigiKey part # 78 | [HM963-ND](https://www.digikey.com/en/products/detail/hammond-manufacturing/1593NBK/1090774) 79 | or [HM964-ND](https://www.digikey.com/en/products/detail/hammond-manufacturing/1593NGY/1090775) 80 | depending on whether you like black or grey). STL and OpenSCAD 81 | files are included for the front and back panels. You could use the 82 | proper Hammond red panel for the front (DigiKey part # 83 | [HM965-ND](https://www.digikey.com/en/products/detail/hammond-manufacturing/1593NIR10/1090776)), 84 | *but* they're only available in 10 packs and their price is highway robbery. 85 | I ended up using a slightly smaller red panel (DigiKey part # 86 | [HM889-ND](https://www.digikey.com/en/products/detail/hammond-manufacturing/1593SIR10/409899)) 87 | that was ~much~ cheaper (it has recently increased in price by 500%) 88 | and available in single units. 89 | 90 | The labels are unbelievably low tech. I print them on a piece of inkjet 91 | transparency film. I then cut that down to size so that it will fit 92 | under the LED opening. Then I attach the trimmed down transparency piece 93 | to a length of matte finish, invisible tape and carefully position it in 94 | place. A bit of careful work with an x-acto knife and you've got 95 | yourself a label that looks like it's part of the panel. If you look 96 | closely at the front panel image you can see the edges of the 97 | transparency film and the tape, but in practice they both essentially 98 | disappear. 99 | 100 | ## The PCB 101 | 102 | The PCB includes cutouts for the two columns that join the case 103 | together, and mounting holes for the 6 standoffs. Also, there's an oddly 104 | shaped cutout in back end to allow a particular IDC DE-9F I had on hand. 105 | It's available from DigiKey (or a very close clone is) but it's fairly 106 | pricey. But there's plenty of room for an ordinary solder cup DE-9F. 107 | You'd most likely want to omit the 10 pin header and just wire the DE-9F 108 | right to the board. 109 | 110 | Unlike the original Retro Wifi Modem, I made no attempt to make this 111 | board by hand. Instead, I took advantage of an introductory offer by a 112 | well known PCB house and had PCBs made. 5 boards for under 20 bucks, and 113 | delivered in under a week? Who could say no? 114 | 115 | ## The Software 116 | 117 | | ![Builtin help](images/Builtin%20help.png "Builtin help") | 118 | |:--:| 119 | | Modem command list | 120 | 121 | The software is naturally quite similar to the original ESP8266 Wifi 122 | modem. There are a few changes (and one fairly major omission): 123 | 124 | * DTR signal handling (AT&D) 125 | * Escape sequence character definition (ATS2) 126 | * no OTA reprogramming (yet!) 127 | 128 | ### First time setup 129 | 130 | The default serial configuration is 9600bps, 8 data bits, no parity, 1 131 | stop bit. 132 | 133 | Here's the commands you need to set up the modem to automatically 134 | connect to your WiFi network: 135 | 136 | 1. `AT$SSID=your WiFi network name` to set the WiFi network that the 137 | modem will connect to when it powers up. 138 | 2. `AT$PASS=your WiFi network password` to set the password for the 139 | network. 140 | 3. `ATC1` to connect to the network. 141 | 4. Optional stuff: 142 | * `AT$SB=speed` to set the default serial speed. 143 | * `AT$SU=dps` to set the data bits, parity and stop bits. 144 | * `ATNETn` to select whether or not to use Telnet protocol. 145 | * `AT&Kn` to use RTS/CTS flow control or not. 146 | * `AT&Dn` to set up DTR handling. 147 | 5. `AT&W` to save the settings. 148 | 149 | Once you've done that, the modem will automatically connect to your WiFi 150 | network on power up and will be ready to "dial up" a connection with 151 | ATDT. 152 | 153 | ### Command Reference 154 | 155 | Multiple AT commands can be typed in on a single line. Spaces between 156 | commands are allowed, but not within commands (i.e. AT S0=1 X1 Q0 is 157 | fine; ATS 0= 1 is not). Commands that take a string as an argument 158 | (e.g. AT$SSID=, AT$TTY=) assume that *everything* that follows is a part 159 | of the string, so no commands are allowed after them. 160 | 161 | Command | Details 162 | ------- | ------- 163 | +++ | 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. 164 | A/ | Repeats the last command entered. Do not type AT or press Enter. 165 | AT | The attention prefix that precedes all command except A/ and +++. 166 | AT? | Displays a help cheatsheet. 167 | ATA | Force the modem to answer an incoming connection when the conditions for auto answer have not been satisfied. 168 | ATC?
ATC*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. 169 | ATDS*n* | Calls the host specified in speed dial slot *n* (0-9). 170 | ATDT[+=-]host[:port] | 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:

Preceding the host name or IP address with a +, = or - character overrides the ATNET setting for the period of the connection.

Once the dial attempt has begun, pressing any key before the connection is established will abort the attempt. 171 | ATE?
ATE*n* | Command mode echo. Enables or disables the display of your typed commands.

172 | ATGET*http://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. 173 | ATH | Hangs up (ends) the current connection. 174 | ATI | Displays the current network status, including sketch build date, WiFi and call connection state, SSID name, IP address, and bytes transferred. 175 | ATNET?
ATNET*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.

The 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.

When 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. 176 | ATO | Return online. Use with the escape code (+++) to toggle between command and online modes. 177 | ATQ?
ATQ*n* | Enable or disable the display of result codes. The default is Q0.

178 | ATRD
ATRT | 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. 179 | ATS0?
ATS0=*n* | Display or set the number of "rings" before answering an incoming connection. Setting `S0=0` means "don't answer". 180 | ATS2?
ATS2=*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. 181 | ATV?
ATV*n* | Display result codes in words or numbers. The default is V1.

182 | ATX?
ATX*n* | Control the amount of information displayed in the result codes. The default is X1 (extended codes).

183 | ATZ | Resets the modem. 184 | AT&D?
AT&D*n* | Display or set the handling of DTR going inactive. The default is &D0 (ignored).

185 | AT&F | Reset the NVRAM contents and current settings to the sketch defaults. All settings, including SSID name, password and speed dial slots are affected. 186 | AT&K?
AT&K*n* | Data flow control. Prevents the modem's buffers for received and transmitted from overflowing.

187 | AT&R?
AT&R=*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. 188 | AT&V*n* | Display current or stored settings.

189 | AT&W | Save current settings to NVRAM. 190 | AT&Zn?
AT&Z*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.

Example: `AT&Z2=particlesbbs.dyndns.org:6400,particles`

This number can then be dialed in any of the following ways:

191 | AT$AE?
AT$AE=*startup AT cmd* | Query or change the command line to be executed when the modem starts up. 192 | AT$AYT | Sends a Telnet "Are You There?" command if connected to a Telnet remote. 193 | AT$BM?
AT$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). 194 | AT$MDNS
AT$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**. 195 | AT$PASS?
AT$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. 196 | AT$SB?
AT$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 Pico 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. 197 | AT$SP?
AT$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. 198 | AT$SSID?
AT$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. 199 | AT$SU?
AT$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. 200 | AT$TTL?
AT$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". 201 | AT$TTS?
AT$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. 202 | AT$TTY?
AT$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". 203 | AT$W?
AT$W=*n* | Startup wait.

204 | 205 | ### Updating the Code 206 | 207 | As I'm writing this, I haven't settled on an OTA programming method that 208 | I like. But I will figure something out; taking the modem apart to do a 209 | code update will get old the very first time I have to do it. Plus, 210 | it means that the Pico W can't be soldered down to the PCB, and that'd 211 | be a nice to have as well. 212 | 213 | ## Status 214 | 215 | It's a work in progress at the moment. The lack of OTA programming is 216 | the big "needs to be done" item. 217 | 218 | As this is my first Pico project, and the first time I've written lwIP 219 | stuff (and the first time I've really had to make changes to CMake 220 | stuff), I've run headlong into all the usual beginner gotchas. And I'm 221 | completely, absolutely sure that I haven't found them all yet. 222 | 223 | The code works reasonably well at the moment; it can call out, you can 224 | call in, Ymodem and Zmodem transfers work, I've figured out why it used 225 | to appear to lock up when I left it alone for 10 minutes (Wifi power 226 | management, if you're wondering)... but I'm under no illusion that there 227 | aren't bugs aplenty yet to be squashed. After all, I found a handful of 228 | problems in the original ESP8266 Retro Wifi modem code while I was 229 | getting the Pico code working, and the ESP code had been pretty much 230 | stable for over two years. 231 | 232 | And I think I may have also discovered why every once in a while, the 233 | modem would get behind a few (or many) characters either on receive or 234 | transmit. The 'volatile' qualifier isn't of as much use with variables 235 | modified by two threads as it is with memory mapped I/O or hardware 236 | registers. To make a long story short, '++var' and '--var' aren't 237 | atomic operations; they're read/modify/write. And every once in a great 238 | while the main thread would be updated a buffer length at the same time 239 | the lwIP thread was updating the same buffer length and whackiness 240 | ensued. 241 | 242 | For the moment, I've taken the naive approach of surrounding the buffer 243 | length writes with disable/re-enable interrupt calls. I think that will 244 | work reasonably well (though if I ever decided to make use of the second 245 | core, it'll fail because interrupts are only disabled on the calling 246 | core). If not, it'll be time to bone up on mutexes and semaphores and 247 | critical sections. 248 | 249 | ### Linux, Telnet, Zmodem and downloading binary files 250 | 251 | Have you used the modem to 'dial' into a Linux box? And have you done a 252 | `sz binary_file` on the Linux box? And at a completely reproducible 253 | point in the file, has the connection dropped? But other binary files 254 | work just fine? Then read on. 255 | 256 | This drove me slightly batty for months on the original Retro modem. I 257 | finally narrowed it down to trying to send blocks of binary data with a 258 | large number of FF bytes. eventually created a test file consisting of 259 | 2K of FF and used that to test with. I could download it through the 260 | modem with Xmodem just fine. Ymodem also worked if I kept the block size 261 | down to 128 bytes - but the connection would drop instantly if I tried 262 | sending 1K blocks. Same thing with Zmodem. 263 | 264 | In fact, if I just tried `cat binary_file`, the connection would 265 | drop. Which eventually got me thinking. Sitting at the console on my 266 | main Linux box, I telnet'd to the same box and logged in. No WiFi modem 267 | involved anywhere, just a telnet session on the console to the same box. 268 | I then did a `cat binary_file`. The telnet connection dropped, and I 269 | was back in my original session. 270 | 271 | It's the Linux telnet daemon. Not the modem at all. 272 | 273 | To prove it to myself, I hooked up WiFi modems to two systems on their 274 | serial ports and had one dial into the other. I could send the all FF 275 | binary file back and forth with Zmodem and Ymodem, no trouble at all. 276 | 277 | But you really, really need to download that binary file through the 278 | modem from a telnet connection to a Linux box? You're not going to be 279 | able to use Zmodem. Ymodem will work (the sy command defaults to 128 280 | byte blocks), as will Xmodem. But not Zmodem. 281 | 282 | Oddly enough, the telnet daemon has no trouble *receiving* the all FF 283 | binary file. Only sending it. Your guess as to why is probably better 284 | than mine. 285 | 286 | ## References 287 | 288 | * [Retro WiFi Modem](https://github.com/mecparts/RetroWiFiModem) 289 | * [WiFi232 - An Internet Hayes Modem for your Retro Computer](http://biosrhythm.com/?page_id=1453)
290 | * [WiFi232's Evil Clone](https://forum.vcfed.org/index.php?threads/wifi232s-evil-clone.1070412/)
291 | * [Jussi Salin's Virtual modem for ESP8266](https://github.com/jsalin/esp8266_modem)
292 | * [Stardot's ESP8266 based virtual modem](https://github.com/stardot/esp8266_modem)
293 | * [Roland Juno's ESP8266 based virtual modem](https://github.com/RolandJuno/esp8266_modem) 294 | 295 | ## Acknowledgements 296 | 297 | * A whole lot of people owe a big vote of thanks to Jussi Salin for 298 | releasing their virtual modem code for the ESP8266 and starting the 299 | ball rolling. 300 | * Paul Rickards for an amazing bit of hardware to draw inspiration from. 301 | * All the Stardot contributors for their work. 302 | * And, of course, Dennis C. Hayes for creating something so simple and 303 | elegant that has stood the test of time. 304 | -------------------------------------------------------------------------------- /case/.gitignore: -------------------------------------------------------------------------------- 1 | *.gcode 2 | dimension_test.scad 3 | pcb_test.* 4 | -------------------------------------------------------------------------------- /case/back_panel.scad: -------------------------------------------------------------------------------- 1 | $fn=64; 2 | eps = 0.04; 3 | inch = 25.4; 4 | 5 | panel_x = 68.76; 6 | panel_y = 19.84; 7 | panel_z = 1.5; 8 | panel_r = 0.05 * inch; 9 | 10 | barrel_x = 0.354*inch; 11 | barrel_y = 0.428*inch; 12 | 13 | module dsub(c,e,a) 14 | { 15 | r=3.35; 16 | h=3.96; 17 | md=3.05; 18 | hull() { 19 | translate([-c/2,h/2,0]) 20 | circle(r=r); 21 | translate([c/2,h/2,0]) 22 | circle(r=r); 23 | translate([-e/2,-h/2,0]) 24 | circle(r=r); 25 | translate([e/2,-h/2,0]) 26 | circle(r=r); 27 | } 28 | translate([-a/2,0,0]) 29 | circle(d=md); 30 | translate([a/2,0,0]) 31 | circle(d=md); 32 | } 33 | 34 | module dsub9() { 35 | dsub(c=13.77,e=12.01,a=24.99); 36 | } 37 | 38 | difference() { 39 | linear_extrude(height=panel_z) { 40 | hull() { 41 | translate([panel_r, panel_r, 0]) { 42 | circle(r=panel_r); 43 | } 44 | translate([panel_x-panel_r, panel_r, 0]) { 45 | circle(r=panel_r); 46 | } 47 | translate([panel_x-panel_r, panel_y-panel_r, 0]) { 48 | circle(r=panel_r); 49 | } 50 | translate([panel_r, panel_y-panel_r, 0]) { 51 | circle(r=panel_r); 52 | } 53 | } 54 | } 55 | translate([panel_x/2 - 12.015, panel_y/2, -eps] ) { 56 | linear_extrude(height=panel_z+2*eps) { 57 | dsub9(); 58 | } 59 | } 60 | translate([panel_x/2+13.33,6.17+barrel_y/2,-eps]) { 61 | linear_extrude(height=panel_z+2*eps) { 62 | square([barrel_x, barrel_y],center=true); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /case/front_panel.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/case/front_panel.ods -------------------------------------------------------------------------------- /case/front_panel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/case/front_panel.pdf -------------------------------------------------------------------------------- /case/front_panel.scad: -------------------------------------------------------------------------------- 1 | $fn=64; 2 | eps = 0.04; 3 | inch = 25.4; 4 | 5 | panel_x = 68.76; 6 | panel_y = 19.84; 7 | panel_z = 1.5; 8 | panel_r = 0.05 * inch; 9 | 10 | lens_x = 2.363 * inch; 11 | lens_y = 0.592 * inch; 12 | lens_z = 0.062 * inch; 13 | 14 | bezel_x = 2.258 * inch; 15 | bezel_y = 0.487 * inch; 16 | bezel_r = 1/16 * inch; 17 | 18 | difference() { 19 | linear_extrude(height=panel_z) { 20 | hull() { 21 | translate([panel_r, panel_r, 0]) { 22 | circle(r=panel_r); 23 | } 24 | translate([panel_x-panel_r, panel_r, 0]) { 25 | circle(r=panel_r); 26 | } 27 | translate([panel_x-panel_r, panel_y-panel_r, 0]) { 28 | circle(r=panel_r); 29 | } 30 | translate([panel_r, panel_y-panel_r, 0]) { 31 | circle(r=panel_r); 32 | } 33 | } 34 | } 35 | translate([panel_x/2,panel_y-1.27-lens_y/2,0.4]) { 36 | linear_extrude(height=panel_z+2*eps) { 37 | square([lens_x+2*eps, lens_y+2*eps],center=true); 38 | } 39 | } 40 | translate([panel_x/2,panel_y-1.27-lens_y/2,-eps]) { 41 | linear_extrude(height=panel_z+2*eps) { 42 | hull() { 43 | translate([-bezel_x/2+bezel_r, -bezel_y/2+bezel_r, 0]) { 44 | circle(r=bezel_r); 45 | } 46 | translate([bezel_x/2-bezel_r, -bezel_y/2+bezel_r, 0]) { 47 | circle(r=bezel_r); 48 | } 49 | translate([bezel_x/2-bezel_r, bezel_y/2-bezel_r, 0]) { 50 | circle(r=bezel_r); 51 | } 52 | translate([-bezel_x/2+bezel_r, bezel_y/2-bezel_r, 0]) { 53 | circle(r=bezel_r); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /images/Back panel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/images/Back panel.jpg -------------------------------------------------------------------------------- /images/Builtin help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/images/Builtin help.png -------------------------------------------------------------------------------- /images/Front panel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/images/Front panel.jpg -------------------------------------------------------------------------------- /images/Interior.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/images/Interior.jpg -------------------------------------------------------------------------------- /images/PicoWifiModem.sch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/images/PicoWifiModem.sch.png -------------------------------------------------------------------------------- /images/Prototype.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/images/Prototype.jpg -------------------------------------------------------------------------------- /kicad/.gitignore: -------------------------------------------------------------------------------- 1 | Pico_Wifi_modem-cache.lib 2 | Pico_Wifi_modem.bak 3 | Pico_Wifi_modem-cache.dcm 4 | Pico_Wifi_modem.kicad_pcb-bak 5 | -------------------------------------------------------------------------------- /kicad/Pico_Wifi_modem-bom.csv: -------------------------------------------------------------------------------- 1 | Reference,Quantity, Value, Price, DigiKey PN 2 | P1,1,CONN_02X05,0.41,ED1543-ND 3 | D1-D8,8,TLPR5600,6.4,TLPR5600-ND 4 | C1-C5,5,100nF,1.55,399-9859-1-ND 5 | C6,1,100nF,0.33,399-9843-ND 6 | C7,1,1uF,2.54,399-3529-ND 7 | CON1,1,BARREL_JACK,1.09,839-54-00166-ND 8 | R1-R8,8,560R,1.28,CF18JT560RCT-ND 9 | U3,1,Pico W,8.88,2648-SC0918CT-ND 10 | U4,1,LM2950ACZ-3.3,1.26,LP2950ACZ-3.3GOS-ND 11 | U1,1,MAX3237ECDWR,5.37,296-36945-1-ND 12 | D12,1,1N5817,0.47,N5817-TPCT-ND 13 | U5,1,AT24C32E-PUM,0.98,AT24C32E-PUM-ND 14 | R12-R13,2,3.9K,0.32,CF18JT3K90CT-ND 15 | U2,1,74HCT245,1.42,296-1612-5-ND 16 | ,1,Hammond 1593NBK case,9.26,HM963-ND  17 | ,1,Hammond red panel,0.88,HM889-ND  18 | ,50,PCB screws,12.46,HM1442-ND 19 | ,1,5V wall adapter,8.92,364-1251-ND  20 | ,1,DE-9F IDC connector,19.9,5746861-4-ND 21 | ,2,D-sub jackscrew,0.94,2057-JS-02-ND 22 | ,1,8 pin DIP socket,0.44,1175-1475-ND 23 | ,1,20 pin DIP socket,0.67,1175-1479-ND 24 | ,1,10 pos IDC socket,0.69,1175-1443-ND  25 | ,1,10 cond ribbon cable,0.95,3M157815-1-ND 26 | -------------------------------------------------------------------------------- /kicad/Pico_Wifi_modem.pro: -------------------------------------------------------------------------------- 1 | update=Thu 10 Nov 2022 03:22:54 PM MST 2 | version=1 3 | last_client=kicad 4 | [pcbnew] 5 | version=1 6 | LastNetListRead= 7 | UseCmpFile=1 8 | PadDrill=0.600000000000 9 | PadDrillOvalY=0.600000000000 10 | PadSizeH=1.500000000000 11 | PadSizeV=1.500000000000 12 | PcbTextSizeV=1.500000000000 13 | PcbTextSizeH=1.500000000000 14 | PcbTextThickness=0.300000000000 15 | ModuleTextSizeV=1.000000000000 16 | ModuleTextSizeH=1.000000000000 17 | ModuleTextSizeThickness=0.150000000000 18 | SolderMaskClearance=0.000000000000 19 | SolderMaskMinWidth=0.000000000000 20 | DrawSegmentWidth=0.200000000000 21 | BoardOutlineThickness=0.100000000000 22 | ModuleOutlineThickness=0.150000000000 23 | [cvpcb] 24 | version=1 25 | NetIExt=net 26 | [general] 27 | version=1 28 | [eeschema] 29 | version=1 30 | LibDir= 31 | -------------------------------------------------------------------------------- /kicad/fp-info-cache: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /kicad/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (lib (name modules)(type KiCad)(uri "$(KIPRJMOD)/modules.pretty")(options "")(descr "")) 3 | ) 4 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem-B.Mask.gbs: -------------------------------------------------------------------------------- 1 | G04 #@! TF.FileFunction,Soldermask,Bot* 2 | %FSLAX46Y46*% 3 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 4 | G04 Created by KiCad (PCBNEW 4.0.5+dfsg1-4) date Sat Oct 15 20:35:36 2022* 5 | %MOMM*% 6 | %LPD*% 7 | G01* 8 | G04 APERTURE LIST* 9 | %ADD10C,0.150000*% 10 | %ADD11C,3.600000*% 11 | %ADD12R,1.700000X1.700000*% 12 | %ADD13C,1.700000*% 13 | %ADD14R,3.900120X3.900120*% 14 | %ADD15R,2.400000X2.400000*% 15 | %ADD16C,2.400000*% 16 | %ADD17C,2.398980*% 17 | %ADD18R,2.398980X2.398980*% 18 | %ADD19R,2.127200X2.127200*% 19 | %ADD20O,2.127200X2.127200*% 20 | %ADD21C,1.797000*% 21 | %ADD22O,2.700000X2.000000*% 22 | %ADD23O,2.100000X2.100000*% 23 | %ADD24R,2.100000X2.100000*% 24 | %ADD25O,2.200000X2.200000*% 25 | %ADD26O,1.900000X1.900000*% 26 | %ADD27O,1.299160X1.901140*% 27 | G04 APERTURE END LIST* 28 | D10* 29 | D11* 30 | X119450000Y-85770000D03* 31 | X119450000Y-132020000D03* 32 | X159450000Y-132020000D03* 33 | X159450000Y-85770000D03* 34 | X189450000Y-85770000D03* 35 | X189450000Y-132020000D03* 36 | D12* 37 | X129286000Y-82042000D03* 38 | D13* 39 | X129286000Y-84542000D03* 40 | D12* 41 | X133858000Y-85471000D03* 42 | D13* 43 | X133858000Y-82971000D03* 44 | D12* 45 | X149733000Y-84582000D03* 46 | D13* 47 | X149733000Y-82082000D03* 48 | D12* 49 | X142748000Y-78359000D03* 50 | D13* 51 | X140248000Y-78359000D03* 52 | D12* 53 | X186182000Y-78359000D03* 54 | D13* 55 | X186182000Y-80859000D03* 56 | D12* 57 | X153162000Y-80772000D03* 58 | D13* 59 | X153162000Y-85852000D03* 60 | D12* 61 | X111760000Y-138176000D03* 62 | D13* 63 | X114260000Y-138176000D03* 64 | D14* 65 | X119610140Y-122230000D03* 66 | X113610660Y-122230000D03* 67 | X116610400Y-126929000D03* 68 | D15* 69 | X205740000Y-84516000D03* 70 | D16* 71 | X205740000Y-87056000D03* 72 | D15* 73 | X205740000Y-91120000D03* 74 | D16* 75 | X205740000Y-93660000D03* 76 | D15* 77 | X205740000Y-97724000D03* 78 | D16* 79 | X205740000Y-100264000D03* 80 | D15* 81 | X205740000Y-104328000D03* 82 | D16* 83 | X205740000Y-106868000D03* 84 | D15* 85 | X205740000Y-110932000D03* 86 | D16* 87 | X205740000Y-113472000D03* 88 | D15* 89 | X205740000Y-117536000D03* 90 | D16* 91 | X205740000Y-120076000D03* 92 | D15* 93 | X205740000Y-124140000D03* 94 | D16* 95 | X205740000Y-126680000D03* 96 | D15* 97 | X205740000Y-130744000D03* 98 | D16* 99 | X205740000Y-133284000D03* 100 | D17* 101 | X172593000Y-133098540D03* 102 | D18* 103 | X182753000Y-133098540D03* 104 | D19* 105 | X128905000Y-101965000D03* 106 | D20* 107 | X126365000Y-101965000D03* 108 | X128905000Y-99425000D03* 109 | X126365000Y-99425000D03* 110 | X128905000Y-96885000D03* 111 | X126365000Y-96885000D03* 112 | X128905000Y-94345000D03* 113 | X126365000Y-94345000D03* 114 | X128905000Y-91805000D03* 115 | X126365000Y-91805000D03* 116 | D21* 117 | X195045000Y-84516000D03* 118 | X202665000Y-84516000D03* 119 | X195045000Y-91120000D03* 120 | X202665000Y-91120000D03* 121 | X195045000Y-97724000D03* 122 | X202665000Y-97724000D03* 123 | X195045000Y-104328000D03* 124 | X202665000Y-104328000D03* 125 | X195045000Y-110932000D03* 126 | X202665000Y-110932000D03* 127 | X195045000Y-117536000D03* 128 | X202665000Y-117536000D03* 129 | X195045000Y-124140000D03* 130 | X202665000Y-124140000D03* 131 | X195045000Y-130744000D03* 132 | X202665000Y-130744000D03* 133 | X147193000Y-131572000D03* 134 | X139573000Y-131572000D03* 135 | X147193000Y-134366000D03* 136 | X139573000Y-134366000D03* 137 | D22* 138 | X174879000Y-79121000D03* 139 | X174879000Y-81661000D03* 140 | X174879000Y-84201000D03* 141 | X174879000Y-86741000D03* 142 | X174879000Y-89281000D03* 143 | X174879000Y-91821000D03* 144 | X174879000Y-94361000D03* 145 | X174879000Y-96901000D03* 146 | X174879000Y-99441000D03* 147 | X174879000Y-101981000D03* 148 | X182499000Y-101981000D03* 149 | X182499000Y-99441000D03* 150 | X182499000Y-96901000D03* 151 | X182499000Y-94361000D03* 152 | X182499000Y-91821000D03* 153 | X182499000Y-89281000D03* 154 | X182499000Y-86741000D03* 155 | X182499000Y-84201000D03* 156 | X182499000Y-81661000D03* 157 | X182499000Y-79121000D03* 158 | D23* 159 | X185293000Y-108331000D03* 160 | X182753000Y-108331000D03* 161 | D24* 162 | X180213000Y-108331000D03* 163 | D23* 164 | X177673000Y-108331000D03* 165 | X175133000Y-108331000D03* 166 | X172593000Y-108331000D03* 167 | X170053000Y-108331000D03* 168 | D24* 169 | X167513000Y-108331000D03* 170 | D23* 171 | X164973000Y-108331000D03* 172 | X162433000Y-108331000D03* 173 | X159893000Y-108331000D03* 174 | X157353000Y-108331000D03* 175 | D24* 176 | X154813000Y-108331000D03* 177 | D23* 178 | X152273000Y-108331000D03* 179 | X149733000Y-108331000D03* 180 | X147193000Y-108331000D03* 181 | X144653000Y-108331000D03* 182 | D24* 183 | X142113000Y-108331000D03* 184 | D23* 185 | X139573000Y-108331000D03* 186 | X137033000Y-108331000D03* 187 | X137033000Y-126111000D03* 188 | X139573000Y-126111000D03* 189 | D24* 190 | X142113000Y-126111000D03* 191 | D23* 192 | X144653000Y-126111000D03* 193 | X147193000Y-126111000D03* 194 | X149733000Y-126111000D03* 195 | X152273000Y-126111000D03* 196 | D24* 197 | X154813000Y-126111000D03* 198 | D23* 199 | X157353000Y-126111000D03* 200 | X159893000Y-126111000D03* 201 | X162433000Y-126111000D03* 202 | X164973000Y-126111000D03* 203 | D24* 204 | X167513000Y-126111000D03* 205 | D23* 206 | X170053000Y-126111000D03* 207 | X172593000Y-126111000D03* 208 | X175133000Y-126111000D03* 209 | X177673000Y-126111000D03* 210 | D24* 211 | X180213000Y-126111000D03* 212 | D23* 213 | X182753000Y-126111000D03* 214 | X185293000Y-126111000D03* 215 | D25* 216 | X185163000Y-119946000D03* 217 | X185163000Y-114496000D03* 218 | D26* 219 | X182133000Y-114796000D03* 220 | X182133000Y-119646000D03* 221 | D23* 222 | X155563000Y-117805100D03* 223 | D24* 224 | X155563000Y-120345100D03* 225 | D23* 226 | X155563000Y-122885100D03* 227 | D27* 228 | X113030000Y-133858000D03* 229 | X114300000Y-133858000D03* 230 | X111760000Y-133858000D03* 231 | D22* 232 | X125095000Y-125730000D03* 233 | X125095000Y-128270000D03* 234 | X125095000Y-130810000D03* 235 | X125095000Y-133350000D03* 236 | X132715000Y-133350000D03* 237 | X132715000Y-130810000D03* 238 | X132715000Y-128270000D03* 239 | X132715000Y-125730000D03* 240 | M02* 241 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem-B.Paste.gbp: -------------------------------------------------------------------------------- 1 | G04 #@! TF.FileFunction,Paste,Bot* 2 | %FSLAX46Y46*% 3 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 4 | G04 Created by KiCad (PCBNEW 4.0.5+dfsg1-4) date Sat Oct 15 20:35:36 2022* 5 | %MOMM*% 6 | %LPD*% 7 | G01* 8 | G04 APERTURE LIST* 9 | %ADD10C,0.150000*% 10 | G04 APERTURE END LIST* 11 | D10* 12 | M02* 13 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem-B.SilkS.gbo: -------------------------------------------------------------------------------- 1 | G04 #@! TF.FileFunction,Legend,Bot* 2 | %FSLAX46Y46*% 3 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 4 | G04 Created by KiCad (PCBNEW 4.0.5+dfsg1-4) date Sat Oct 15 20:35:36 2022* 5 | %MOMM*% 6 | %LPD*% 7 | G01* 8 | G04 APERTURE LIST* 9 | %ADD10C,0.150000*% 10 | %ADD11C,0.300000*% 11 | %ADD12C,3.600000*% 12 | %ADD13R,1.700000X1.700000*% 13 | %ADD14C,1.700000*% 14 | %ADD15R,3.900120X3.900120*% 15 | %ADD16R,2.400000X2.400000*% 16 | %ADD17C,2.400000*% 17 | %ADD18C,2.398980*% 18 | %ADD19R,2.398980X2.398980*% 19 | %ADD20R,2.127200X2.127200*% 20 | %ADD21O,2.127200X2.127200*% 21 | %ADD22C,1.797000*% 22 | %ADD23O,2.700000X2.000000*% 23 | %ADD24O,2.100000X2.100000*% 24 | %ADD25R,2.100000X2.100000*% 25 | %ADD26O,2.200000X2.200000*% 26 | %ADD27O,1.900000X1.900000*% 27 | %ADD28O,1.299160X1.901140*% 28 | G04 APERTURE END LIST* 29 | D10* 30 | D11* 31 | X173171286Y-112301571D02* 32 | X173171286Y-110801571D01* 33 | X172599858Y-110801571D01* 34 | X172457000Y-110873000D01* 35 | X172385572Y-110944429D01* 36 | X172314143Y-111087286D01* 37 | X172314143Y-111301571D01* 38 | X172385572Y-111444429D01* 39 | X172457000Y-111515857D01* 40 | X172599858Y-111587286D01* 41 | X173171286Y-111587286D01* 42 | X171671286Y-112301571D02* 43 | X171671286Y-111301571D01* 44 | X171671286Y-110801571D02* 45 | X171742715Y-110873000D01* 46 | X171671286Y-110944429D01* 47 | X171599858Y-110873000D01* 48 | X171671286Y-110801571D01* 49 | X171671286Y-110944429D01* 50 | X170314143Y-112230143D02* 51 | X170457000Y-112301571D01* 52 | X170742714Y-112301571D01* 53 | X170885572Y-112230143D01* 54 | X170957000Y-112158714D01* 55 | X171028429Y-112015857D01* 56 | X171028429Y-111587286D01* 57 | X170957000Y-111444429D01* 58 | X170885572Y-111373000D01* 59 | X170742714Y-111301571D01* 60 | X170457000Y-111301571D01* 61 | X170314143Y-111373000D01* 62 | X169457000Y-112301571D02* 63 | X169599858Y-112230143D01* 64 | X169671286Y-112158714D01* 65 | X169742715Y-112015857D01* 66 | X169742715Y-111587286D01* 67 | X169671286Y-111444429D01* 68 | X169599858Y-111373000D01* 69 | X169457000Y-111301571D01* 70 | X169242715Y-111301571D01* 71 | X169099858Y-111373000D01* 72 | X169028429Y-111444429D01* 73 | X168957000Y-111587286D01* 74 | X168957000Y-112015857D01* 75 | X169028429Y-112158714D01* 76 | X169099858Y-112230143D01* 77 | X169242715Y-112301571D01* 78 | X169457000Y-112301571D01* 79 | X167314143Y-110801571D02* 80 | X166957000Y-112301571D01* 81 | X166671286Y-111230143D01* 82 | X166385572Y-112301571D01* 83 | X166028429Y-110801571D01* 84 | X165457000Y-112301571D02* 85 | X165457000Y-111301571D01* 86 | X165457000Y-110801571D02* 87 | X165528429Y-110873000D01* 88 | X165457000Y-110944429D01* 89 | X165385572Y-110873000D01* 90 | X165457000Y-110801571D01* 91 | X165457000Y-110944429D01* 92 | X164957000Y-111301571D02* 93 | X164385571Y-111301571D01* 94 | X164742714Y-112301571D02* 95 | X164742714Y-111015857D01* 96 | X164671286Y-110873000D01* 97 | X164528428Y-110801571D01* 98 | X164385571Y-110801571D01* 99 | X163885571Y-112301571D02* 100 | X163885571Y-111301571D01* 101 | X163885571Y-110801571D02* 102 | X163957000Y-110873000D01* 103 | X163885571Y-110944429D01* 104 | X163814143Y-110873000D01* 105 | X163885571Y-110801571D01* 106 | X163885571Y-110944429D01* 107 | X162028428Y-112301571D02* 108 | X162028428Y-111301571D01* 109 | X162028428Y-111444429D02* 110 | X161957000Y-111373000D01* 111 | X161814142Y-111301571D01* 112 | X161599857Y-111301571D01* 113 | X161457000Y-111373000D01* 114 | X161385571Y-111515857D01* 115 | X161385571Y-112301571D01* 116 | X161385571Y-111515857D02* 117 | X161314142Y-111373000D01* 118 | X161171285Y-111301571D01* 119 | X160957000Y-111301571D01* 120 | X160814142Y-111373000D01* 121 | X160742714Y-111515857D01* 122 | X160742714Y-112301571D01* 123 | X159814142Y-112301571D02* 124 | X159957000Y-112230143D01* 125 | X160028428Y-112158714D01* 126 | X160099857Y-112015857D01* 127 | X160099857Y-111587286D01* 128 | X160028428Y-111444429D01* 129 | X159957000Y-111373000D01* 130 | X159814142Y-111301571D01* 131 | X159599857Y-111301571D01* 132 | X159457000Y-111373000D01* 133 | X159385571Y-111444429D01* 134 | X159314142Y-111587286D01* 135 | X159314142Y-112015857D01* 136 | X159385571Y-112158714D01* 137 | X159457000Y-112230143D01* 138 | X159599857Y-112301571D01* 139 | X159814142Y-112301571D01* 140 | X158028428Y-112301571D02* 141 | X158028428Y-110801571D01* 142 | X158028428Y-112230143D02* 143 | X158171285Y-112301571D01* 144 | X158456999Y-112301571D01* 145 | X158599857Y-112230143D01* 146 | X158671285Y-112158714D01* 147 | X158742714Y-112015857D01* 148 | X158742714Y-111587286D01* 149 | X158671285Y-111444429D01* 150 | X158599857Y-111373000D01* 151 | X158456999Y-111301571D01* 152 | X158171285Y-111301571D01* 153 | X158028428Y-111373000D01* 154 | X156742714Y-112230143D02* 155 | X156885571Y-112301571D01* 156 | X157171285Y-112301571D01* 157 | X157314142Y-112230143D01* 158 | X157385571Y-112087286D01* 159 | X157385571Y-111515857D01* 160 | X157314142Y-111373000D01* 161 | X157171285Y-111301571D01* 162 | X156885571Y-111301571D01* 163 | X156742714Y-111373000D01* 164 | X156671285Y-111515857D01* 165 | X156671285Y-111658714D01* 166 | X157385571Y-111801571D01* 167 | X156028428Y-112301571D02* 168 | X156028428Y-111301571D01* 169 | X156028428Y-111444429D02* 170 | X155957000Y-111373000D01* 171 | X155814142Y-111301571D01* 172 | X155599857Y-111301571D01* 173 | X155457000Y-111373000D01* 174 | X155385571Y-111515857D01* 175 | X155385571Y-112301571D01* 176 | X155385571Y-111515857D02* 177 | X155314142Y-111373000D01* 178 | X155171285Y-111301571D01* 179 | X154957000Y-111301571D01* 180 | X154814142Y-111373000D01* 181 | X154742714Y-111515857D01* 182 | X154742714Y-112301571D01* 183 | X168528428Y-113351571D02* 184 | X168028428Y-114851571D01* 185 | X167528428Y-113351571D01* 186 | X166457000Y-114780143D02* 187 | X166599857Y-114851571D01* 188 | X166885571Y-114851571D01* 189 | X167028428Y-114780143D01* 190 | X167099857Y-114637286D01* 191 | X167099857Y-114065857D01* 192 | X167028428Y-113923000D01* 193 | X166885571Y-113851571D01* 194 | X166599857Y-113851571D01* 195 | X166457000Y-113923000D01* 196 | X166385571Y-114065857D01* 197 | X166385571Y-114208714D01* 198 | X167099857Y-114351571D01* 199 | X165742714Y-114851571D02* 200 | X165742714Y-113851571D01* 201 | X165742714Y-114137286D02* 202 | X165671286Y-113994429D01* 203 | X165599857Y-113923000D01* 204 | X165457000Y-113851571D01* 205 | X165314143Y-113851571D01* 206 | X164885572Y-114780143D02* 207 | X164742715Y-114851571D01* 208 | X164457000Y-114851571D01* 209 | X164314143Y-114780143D01* 210 | X164242715Y-114637286D01* 211 | X164242715Y-114565857D01* 212 | X164314143Y-114423000D01* 213 | X164457000Y-114351571D01* 214 | X164671286Y-114351571D01* 215 | X164814143Y-114280143D01* 216 | X164885572Y-114137286D01* 217 | X164885572Y-114065857D01* 218 | X164814143Y-113923000D01* 219 | X164671286Y-113851571D01* 220 | X164457000Y-113851571D01* 221 | X164314143Y-113923000D01* 222 | X162171286Y-113351571D02* 223 | X162028429Y-113351571D01* 224 | X161885572Y-113423000D01* 225 | X161814143Y-113494429D01* 226 | X161742714Y-113637286D01* 227 | X161671286Y-113923000D01* 228 | X161671286Y-114280143D01* 229 | X161742714Y-114565857D01* 230 | X161814143Y-114708714D01* 231 | X161885572Y-114780143D01* 232 | X162028429Y-114851571D01* 233 | X162171286Y-114851571D01* 234 | X162314143Y-114780143D01* 235 | X162385572Y-114708714D01* 236 | X162457000Y-114565857D01* 237 | X162528429Y-114280143D01* 238 | X162528429Y-113923000D01* 239 | X162457000Y-113637286D01* 240 | X162385572Y-113494429D01* 241 | X162314143Y-113423000D01* 242 | X162171286Y-113351571D01* 243 | X161028429Y-114708714D02* 244 | X160957001Y-114780143D01* 245 | X161028429Y-114851571D01* 246 | X161099858Y-114780143D01* 247 | X161028429Y-114708714D01* 248 | X161028429Y-114851571D01* 249 | X160385572Y-113494429D02* 250 | X160314143Y-113423000D01* 251 | X160171286Y-113351571D01* 252 | X159814143Y-113351571D01* 253 | X159671286Y-113423000D01* 254 | X159599857Y-113494429D01* 255 | X159528429Y-113637286D01* 256 | X159528429Y-113780143D01* 257 | X159599857Y-113994429D01* 258 | X160457000Y-114851571D01* 259 | X159528429Y-114851571D01* 260 | X170599856Y-115901571D02* 261 | X170314142Y-115901571D01* 262 | X170171284Y-115973000D01* 263 | X170028427Y-116115857D01* 264 | X169956999Y-116401571D01* 265 | X169956999Y-116901571D01* 266 | X170028427Y-117187286D01* 267 | X170171284Y-117330143D01* 268 | X170314142Y-117401571D01* 269 | X170599856Y-117401571D01* 270 | X170742713Y-117330143D01* 271 | X170885570Y-117187286D01* 272 | X170956999Y-116901571D01* 273 | X170956999Y-116401571D01* 274 | X170885570Y-116115857D01* 275 | X170742713Y-115973000D01* 276 | X170599856Y-115901571D01* 277 | X168671284Y-117330143D02* 278 | X168814141Y-117401571D01* 279 | X169099855Y-117401571D01* 280 | X169242713Y-117330143D01* 281 | X169314141Y-117258714D01* 282 | X169385570Y-117115857D01* 283 | X169385570Y-116687286D01* 284 | X169314141Y-116544429D01* 285 | X169242713Y-116473000D01* 286 | X169099855Y-116401571D01* 287 | X168814141Y-116401571D01* 288 | X168671284Y-116473000D01* 289 | X168242713Y-116401571D02* 290 | X167671284Y-116401571D01* 291 | X168028427Y-115901571D02* 292 | X168028427Y-117187286D01* 293 | X167956999Y-117330143D01* 294 | X167814141Y-117401571D01* 295 | X167671284Y-117401571D01* 296 | X165242713Y-117401571D02* 297 | X166099856Y-117401571D01* 298 | X165671284Y-117401571D02* 299 | X165671284Y-115901571D01* 300 | X165814141Y-116115857D01* 301 | X165956999Y-116258714D01* 302 | X166099856Y-116330143D01* 303 | X163885570Y-115901571D02* 304 | X164599856Y-115901571D01* 305 | X164671285Y-116615857D01* 306 | X164599856Y-116544429D01* 307 | X164456999Y-116473000D01* 308 | X164099856Y-116473000D01* 309 | X163956999Y-116544429D01* 310 | X163885570Y-116615857D01* 311 | X163814142Y-116758714D01* 312 | X163814142Y-117115857D01* 313 | X163885570Y-117258714D01* 314 | X163956999Y-117330143D01* 315 | X164099856Y-117401571D01* 316 | X164456999Y-117401571D01* 317 | X164599856Y-117330143D01* 318 | X164671285Y-117258714D01* 319 | X162099857Y-116044429D02* 320 | X162028428Y-115973000D01* 321 | X161885571Y-115901571D01* 322 | X161528428Y-115901571D01* 323 | X161385571Y-115973000D01* 324 | X161314142Y-116044429D01* 325 | X161242714Y-116187286D01* 326 | X161242714Y-116330143D01* 327 | X161314142Y-116544429D01* 328 | X162171285Y-117401571D01* 329 | X161242714Y-117401571D01* 330 | X160314143Y-115901571D02* 331 | X160171286Y-115901571D01* 332 | X160028429Y-115973000D01* 333 | X159957000Y-116044429D01* 334 | X159885571Y-116187286D01* 335 | X159814143Y-116473000D01* 336 | X159814143Y-116830143D01* 337 | X159885571Y-117115857D01* 338 | X159957000Y-117258714D01* 339 | X160028429Y-117330143D01* 340 | X160171286Y-117401571D01* 341 | X160314143Y-117401571D01* 342 | X160457000Y-117330143D01* 343 | X160528429Y-117258714D01* 344 | X160599857Y-117115857D01* 345 | X160671286Y-116830143D01* 346 | X160671286Y-116473000D01* 347 | X160599857Y-116187286D01* 348 | X160528429Y-116044429D01* 349 | X160457000Y-115973000D01* 350 | X160314143Y-115901571D01* 351 | X159242715Y-116044429D02* 352 | X159171286Y-115973000D01* 353 | X159028429Y-115901571D01* 354 | X158671286Y-115901571D01* 355 | X158528429Y-115973000D01* 356 | X158457000Y-116044429D01* 357 | X158385572Y-116187286D01* 358 | X158385572Y-116330143D01* 359 | X158457000Y-116544429D01* 360 | X159314143Y-117401571D01* 361 | X158385572Y-117401571D01* 362 | X157814144Y-116044429D02* 363 | X157742715Y-115973000D01* 364 | X157599858Y-115901571D01* 365 | X157242715Y-115901571D01* 366 | X157099858Y-115973000D01* 367 | X157028429Y-116044429D01* 368 | X156957001Y-116187286D01* 369 | X156957001Y-116330143D01* 370 | X157028429Y-116544429D01* 371 | X157885572Y-117401571D01* 372 | X156957001Y-117401571D01* 373 | %LPC*% 374 | D12* 375 | X119450000Y-85770000D03* 376 | X119450000Y-132020000D03* 377 | X159450000Y-132020000D03* 378 | X159450000Y-85770000D03* 379 | X189450000Y-85770000D03* 380 | X189450000Y-132020000D03* 381 | D13* 382 | X129286000Y-82042000D03* 383 | D14* 384 | X129286000Y-84542000D03* 385 | D13* 386 | X133858000Y-85471000D03* 387 | D14* 388 | X133858000Y-82971000D03* 389 | D13* 390 | X149733000Y-84582000D03* 391 | D14* 392 | X149733000Y-82082000D03* 393 | D13* 394 | X142748000Y-78359000D03* 395 | D14* 396 | X140248000Y-78359000D03* 397 | D13* 398 | X186182000Y-78359000D03* 399 | D14* 400 | X186182000Y-80859000D03* 401 | D13* 402 | X153162000Y-80772000D03* 403 | D14* 404 | X153162000Y-85852000D03* 405 | D13* 406 | X111760000Y-138176000D03* 407 | D14* 408 | X114260000Y-138176000D03* 409 | D15* 410 | X119610140Y-122230000D03* 411 | X113610660Y-122230000D03* 412 | X116610400Y-126929000D03* 413 | D16* 414 | X205740000Y-84516000D03* 415 | D17* 416 | X205740000Y-87056000D03* 417 | D16* 418 | X205740000Y-91120000D03* 419 | D17* 420 | X205740000Y-93660000D03* 421 | D16* 422 | X205740000Y-97724000D03* 423 | D17* 424 | X205740000Y-100264000D03* 425 | D16* 426 | X205740000Y-104328000D03* 427 | D17* 428 | X205740000Y-106868000D03* 429 | D16* 430 | X205740000Y-110932000D03* 431 | D17* 432 | X205740000Y-113472000D03* 433 | D16* 434 | X205740000Y-117536000D03* 435 | D17* 436 | X205740000Y-120076000D03* 437 | D16* 438 | X205740000Y-124140000D03* 439 | D17* 440 | X205740000Y-126680000D03* 441 | D16* 442 | X205740000Y-130744000D03* 443 | D17* 444 | X205740000Y-133284000D03* 445 | D18* 446 | X172593000Y-133098540D03* 447 | D19* 448 | X182753000Y-133098540D03* 449 | D20* 450 | X128905000Y-101965000D03* 451 | D21* 452 | X126365000Y-101965000D03* 453 | X128905000Y-99425000D03* 454 | X126365000Y-99425000D03* 455 | X128905000Y-96885000D03* 456 | X126365000Y-96885000D03* 457 | X128905000Y-94345000D03* 458 | X126365000Y-94345000D03* 459 | X128905000Y-91805000D03* 460 | X126365000Y-91805000D03* 461 | D22* 462 | X195045000Y-84516000D03* 463 | X202665000Y-84516000D03* 464 | X195045000Y-91120000D03* 465 | X202665000Y-91120000D03* 466 | X195045000Y-97724000D03* 467 | X202665000Y-97724000D03* 468 | X195045000Y-104328000D03* 469 | X202665000Y-104328000D03* 470 | X195045000Y-110932000D03* 471 | X202665000Y-110932000D03* 472 | X195045000Y-117536000D03* 473 | X202665000Y-117536000D03* 474 | X195045000Y-124140000D03* 475 | X202665000Y-124140000D03* 476 | X195045000Y-130744000D03* 477 | X202665000Y-130744000D03* 478 | X147193000Y-131572000D03* 479 | X139573000Y-131572000D03* 480 | X147193000Y-134366000D03* 481 | X139573000Y-134366000D03* 482 | D23* 483 | X174879000Y-79121000D03* 484 | X174879000Y-81661000D03* 485 | X174879000Y-84201000D03* 486 | X174879000Y-86741000D03* 487 | X174879000Y-89281000D03* 488 | X174879000Y-91821000D03* 489 | X174879000Y-94361000D03* 490 | X174879000Y-96901000D03* 491 | X174879000Y-99441000D03* 492 | X174879000Y-101981000D03* 493 | X182499000Y-101981000D03* 494 | X182499000Y-99441000D03* 495 | X182499000Y-96901000D03* 496 | X182499000Y-94361000D03* 497 | X182499000Y-91821000D03* 498 | X182499000Y-89281000D03* 499 | X182499000Y-86741000D03* 500 | X182499000Y-84201000D03* 501 | X182499000Y-81661000D03* 502 | X182499000Y-79121000D03* 503 | D24* 504 | X185293000Y-108331000D03* 505 | X182753000Y-108331000D03* 506 | D25* 507 | X180213000Y-108331000D03* 508 | D24* 509 | X177673000Y-108331000D03* 510 | X175133000Y-108331000D03* 511 | X172593000Y-108331000D03* 512 | X170053000Y-108331000D03* 513 | D25* 514 | X167513000Y-108331000D03* 515 | D24* 516 | X164973000Y-108331000D03* 517 | X162433000Y-108331000D03* 518 | X159893000Y-108331000D03* 519 | X157353000Y-108331000D03* 520 | D25* 521 | X154813000Y-108331000D03* 522 | D24* 523 | X152273000Y-108331000D03* 524 | X149733000Y-108331000D03* 525 | X147193000Y-108331000D03* 526 | X144653000Y-108331000D03* 527 | D25* 528 | X142113000Y-108331000D03* 529 | D24* 530 | X139573000Y-108331000D03* 531 | X137033000Y-108331000D03* 532 | X137033000Y-126111000D03* 533 | X139573000Y-126111000D03* 534 | D25* 535 | X142113000Y-126111000D03* 536 | D24* 537 | X144653000Y-126111000D03* 538 | X147193000Y-126111000D03* 539 | X149733000Y-126111000D03* 540 | X152273000Y-126111000D03* 541 | D25* 542 | X154813000Y-126111000D03* 543 | D24* 544 | X157353000Y-126111000D03* 545 | X159893000Y-126111000D03* 546 | X162433000Y-126111000D03* 547 | X164973000Y-126111000D03* 548 | D25* 549 | X167513000Y-126111000D03* 550 | D24* 551 | X170053000Y-126111000D03* 552 | X172593000Y-126111000D03* 553 | X175133000Y-126111000D03* 554 | X177673000Y-126111000D03* 555 | D25* 556 | X180213000Y-126111000D03* 557 | D24* 558 | X182753000Y-126111000D03* 559 | X185293000Y-126111000D03* 560 | D26* 561 | X185163000Y-119946000D03* 562 | X185163000Y-114496000D03* 563 | D27* 564 | X182133000Y-114796000D03* 565 | X182133000Y-119646000D03* 566 | D24* 567 | X155563000Y-117805100D03* 568 | D25* 569 | X155563000Y-120345100D03* 570 | D24* 571 | X155563000Y-122885100D03* 572 | D28* 573 | X113030000Y-133858000D03* 574 | X114300000Y-133858000D03* 575 | X111760000Y-133858000D03* 576 | D23* 577 | X125095000Y-125730000D03* 578 | X125095000Y-128270000D03* 579 | X125095000Y-130810000D03* 580 | X125095000Y-133350000D03* 581 | X132715000Y-133350000D03* 582 | X132715000Y-130810000D03* 583 | X132715000Y-128270000D03* 584 | X132715000Y-125730000D03* 585 | M02* 586 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem-Edge.Cuts.gm1: -------------------------------------------------------------------------------- 1 | G04 #@! TF.FileFunction,Profile,NP* 2 | %FSLAX46Y46*% 3 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 4 | G04 Created by KiCad (PCBNEW 4.0.5+dfsg1-4) date Sat Oct 15 20:35:36 2022* 5 | %MOMM*% 6 | %LPD*% 7 | G01* 8 | G04 APERTURE LIST* 9 | %ADD10C,0.150000*% 10 | G04 APERTURE END LIST* 11 | D10* 12 | X109720000Y-75830000D02* 13 | X162485000Y-75830000D01* 14 | X162485000Y-75830000D02* 15 | X162485000Y-80975000D01* 16 | X162485000Y-80975000D02* 17 | G75* 18 | G03X169115000Y-80975000I3315000J0D01* 19 | G01* 20 | X169115000Y-80975000D02* 21 | X169115000Y-75830000D01* 22 | X169115000Y-75830000D02* 23 | X209720000Y-75830000D01* 24 | X209720000Y-75830000D02* 25 | X209720000Y-141970000D01* 26 | X209720000Y-141970000D02* 27 | X169115000Y-141970000D01* 28 | X169115000Y-141970000D02* 29 | X169115000Y-136825000D01* 30 | X169115000Y-136825000D02* 31 | G75* 32 | G03X162485000Y-136825000I-3315000J0D01* 33 | G01* 34 | X162485000Y-136825000D02* 35 | X162485000Y-141970000D01* 36 | X162485000Y-141970000D02* 37 | X109720000Y-141970000D01* 38 | X109720000Y-141970000D02* 39 | X109720000Y-112629000D01* 40 | X109720000Y-112629000D02* 41 | X111980600Y-112629000D01* 42 | X111980600Y-112629000D02* 43 | X111980600Y-106498900D01* 44 | X111980600Y-106498900D02* 45 | X116832000Y-106498900D01* 46 | X116832000Y-106498900D02* 47 | X116832000Y-87271100D01* 48 | X116832000Y-87271100D02* 49 | X111980600Y-87271100D01* 50 | X111980600Y-87271100D02* 51 | X111980600Y-81141000D01* 52 | X111980600Y-81141000D02* 53 | X109720000Y-81141000D01* 54 | X109720000Y-81141000D02* 55 | X109720000Y-75830000D01* 56 | M02* 57 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem-F.Mask.gts: -------------------------------------------------------------------------------- 1 | G04 #@! TF.FileFunction,Soldermask,Top* 2 | %FSLAX46Y46*% 3 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 4 | G04 Created by KiCad (PCBNEW 4.0.5+dfsg1-4) date Sat Oct 15 20:35:36 2022* 5 | %MOMM*% 6 | %LPD*% 7 | G01* 8 | G04 APERTURE LIST* 9 | %ADD10C,0.150000*% 10 | %ADD11C,3.600000*% 11 | %ADD12R,1.700000X1.700000*% 12 | %ADD13C,1.700000*% 13 | %ADD14R,3.900120X3.900120*% 14 | %ADD15R,2.400000X2.400000*% 15 | %ADD16C,2.400000*% 16 | %ADD17C,2.398980*% 17 | %ADD18R,2.398980X2.398980*% 18 | %ADD19R,2.127200X2.127200*% 19 | %ADD20O,2.127200X2.127200*% 20 | %ADD21C,1.797000*% 21 | %ADD22R,2.400000X1.000000*% 22 | %ADD23O,2.700000X2.000000*% 23 | %ADD24O,2.100000X2.100000*% 24 | %ADD25R,2.100000X2.100000*% 25 | %ADD26O,2.200000X2.200000*% 26 | %ADD27O,1.900000X1.900000*% 27 | %ADD28R,2.100000X3.900000*% 28 | %ADD29O,1.299160X1.901140*% 29 | G04 APERTURE END LIST* 30 | D10* 31 | D11* 32 | X119450000Y-85770000D03* 33 | X119450000Y-132020000D03* 34 | X159450000Y-132020000D03* 35 | X159450000Y-85770000D03* 36 | X189450000Y-85770000D03* 37 | X189450000Y-132020000D03* 38 | D12* 39 | X129286000Y-82042000D03* 40 | D13* 41 | X129286000Y-84542000D03* 42 | D12* 43 | X133858000Y-85471000D03* 44 | D13* 45 | X133858000Y-82971000D03* 46 | D12* 47 | X149733000Y-84582000D03* 48 | D13* 49 | X149733000Y-82082000D03* 50 | D12* 51 | X142748000Y-78359000D03* 52 | D13* 53 | X140248000Y-78359000D03* 54 | D12* 55 | X186182000Y-78359000D03* 56 | D13* 57 | X186182000Y-80859000D03* 58 | D12* 59 | X153162000Y-80772000D03* 60 | D13* 61 | X153162000Y-85852000D03* 62 | D12* 63 | X111760000Y-138176000D03* 64 | D13* 65 | X114260000Y-138176000D03* 66 | D14* 67 | X119610140Y-122230000D03* 68 | X113610660Y-122230000D03* 69 | X116610400Y-126929000D03* 70 | D15* 71 | X205740000Y-84516000D03* 72 | D16* 73 | X205740000Y-87056000D03* 74 | D15* 75 | X205740000Y-91120000D03* 76 | D16* 77 | X205740000Y-93660000D03* 78 | D15* 79 | X205740000Y-97724000D03* 80 | D16* 81 | X205740000Y-100264000D03* 82 | D15* 83 | X205740000Y-104328000D03* 84 | D16* 85 | X205740000Y-106868000D03* 86 | D15* 87 | X205740000Y-110932000D03* 88 | D16* 89 | X205740000Y-113472000D03* 90 | D15* 91 | X205740000Y-117536000D03* 92 | D16* 93 | X205740000Y-120076000D03* 94 | D15* 95 | X205740000Y-124140000D03* 96 | D16* 97 | X205740000Y-126680000D03* 98 | D15* 99 | X205740000Y-130744000D03* 100 | D16* 101 | X205740000Y-133284000D03* 102 | D17* 103 | X172593000Y-133098540D03* 104 | D18* 105 | X182753000Y-133098540D03* 106 | D19* 107 | X128905000Y-101965000D03* 108 | D20* 109 | X126365000Y-101965000D03* 110 | X128905000Y-99425000D03* 111 | X126365000Y-99425000D03* 112 | X128905000Y-96885000D03* 113 | X126365000Y-96885000D03* 114 | X128905000Y-94345000D03* 115 | X126365000Y-94345000D03* 116 | X128905000Y-91805000D03* 117 | X126365000Y-91805000D03* 118 | D21* 119 | X195045000Y-84516000D03* 120 | X202665000Y-84516000D03* 121 | X195045000Y-91120000D03* 122 | X202665000Y-91120000D03* 123 | X195045000Y-97724000D03* 124 | X202665000Y-97724000D03* 125 | X195045000Y-104328000D03* 126 | X202665000Y-104328000D03* 127 | X195045000Y-110932000D03* 128 | X202665000Y-110932000D03* 129 | X195045000Y-117536000D03* 130 | X202665000Y-117536000D03* 131 | X195045000Y-124140000D03* 132 | X202665000Y-124140000D03* 133 | X195045000Y-130744000D03* 134 | X202665000Y-130744000D03* 135 | X147193000Y-131572000D03* 136 | X139573000Y-131572000D03* 137 | X147193000Y-134366000D03* 138 | X139573000Y-134366000D03* 139 | D22* 140 | X136905000Y-81661000D03* 141 | X136905000Y-82931000D03* 142 | X136905000Y-84201000D03* 143 | X136905000Y-85471000D03* 144 | X136905000Y-86741000D03* 145 | X136905000Y-88011000D03* 146 | X136905000Y-89281000D03* 147 | X136905000Y-90551000D03* 148 | X136905000Y-91821000D03* 149 | X136905000Y-93091000D03* 150 | X136905000Y-94361000D03* 151 | X136905000Y-95631000D03* 152 | X136905000Y-96901000D03* 153 | X136905000Y-98171000D03* 154 | X146305000Y-98171000D03* 155 | X146305000Y-96901000D03* 156 | X146305000Y-95631000D03* 157 | X146305000Y-94361000D03* 158 | X146305000Y-93091000D03* 159 | X146305000Y-91821000D03* 160 | X146305000Y-90551000D03* 161 | X146305000Y-89281000D03* 162 | X146305000Y-88011000D03* 163 | X146305000Y-86741000D03* 164 | X146305000Y-85471000D03* 165 | X146305000Y-84201000D03* 166 | X146305000Y-82931000D03* 167 | X146305000Y-81661000D03* 168 | D23* 169 | X174879000Y-79121000D03* 170 | X174879000Y-81661000D03* 171 | X174879000Y-84201000D03* 172 | X174879000Y-86741000D03* 173 | X174879000Y-89281000D03* 174 | X174879000Y-91821000D03* 175 | X174879000Y-94361000D03* 176 | X174879000Y-96901000D03* 177 | X174879000Y-99441000D03* 178 | X174879000Y-101981000D03* 179 | X182499000Y-101981000D03* 180 | X182499000Y-99441000D03* 181 | X182499000Y-96901000D03* 182 | X182499000Y-94361000D03* 183 | X182499000Y-91821000D03* 184 | X182499000Y-89281000D03* 185 | X182499000Y-86741000D03* 186 | X182499000Y-84201000D03* 187 | X182499000Y-81661000D03* 188 | X182499000Y-79121000D03* 189 | D24* 190 | X185293000Y-108331000D03* 191 | X182753000Y-108331000D03* 192 | D25* 193 | X180213000Y-108331000D03* 194 | D24* 195 | X177673000Y-108331000D03* 196 | X175133000Y-108331000D03* 197 | X172593000Y-108331000D03* 198 | X170053000Y-108331000D03* 199 | D25* 200 | X167513000Y-108331000D03* 201 | D24* 202 | X164973000Y-108331000D03* 203 | X162433000Y-108331000D03* 204 | X159893000Y-108331000D03* 205 | X157353000Y-108331000D03* 206 | D25* 207 | X154813000Y-108331000D03* 208 | D24* 209 | X152273000Y-108331000D03* 210 | X149733000Y-108331000D03* 211 | X147193000Y-108331000D03* 212 | X144653000Y-108331000D03* 213 | D25* 214 | X142113000Y-108331000D03* 215 | D24* 216 | X139573000Y-108331000D03* 217 | X137033000Y-108331000D03* 218 | X137033000Y-126111000D03* 219 | X139573000Y-126111000D03* 220 | D25* 221 | X142113000Y-126111000D03* 222 | D24* 223 | X144653000Y-126111000D03* 224 | X147193000Y-126111000D03* 225 | X149733000Y-126111000D03* 226 | X152273000Y-126111000D03* 227 | D25* 228 | X154813000Y-126111000D03* 229 | D24* 230 | X157353000Y-126111000D03* 231 | X159893000Y-126111000D03* 232 | X162433000Y-126111000D03* 233 | X164973000Y-126111000D03* 234 | D25* 235 | X167513000Y-126111000D03* 236 | D24* 237 | X170053000Y-126111000D03* 238 | X172593000Y-126111000D03* 239 | X175133000Y-126111000D03* 240 | X177673000Y-126111000D03* 241 | D25* 242 | X180213000Y-126111000D03* 243 | D24* 244 | X182753000Y-126111000D03* 245 | X185293000Y-126111000D03* 246 | D26* 247 | X185163000Y-119946000D03* 248 | X185163000Y-114496000D03* 249 | D27* 250 | X182133000Y-114796000D03* 251 | X182133000Y-119646000D03* 252 | D24* 253 | X155563000Y-117805100D03* 254 | D25* 255 | X155563000Y-120345100D03* 256 | D24* 257 | X155563000Y-122885100D03* 258 | D28* 259 | X185293000Y-107431000D03* 260 | X182753000Y-107431000D03* 261 | X180213000Y-107431000D03* 262 | X177673000Y-107431000D03* 263 | X175133000Y-107431000D03* 264 | X172593000Y-107431000D03* 265 | X170053000Y-107431000D03* 266 | X167513000Y-107431000D03* 267 | X164973000Y-107431000D03* 268 | X162433000Y-107431000D03* 269 | X159893000Y-107431000D03* 270 | X157353000Y-107431000D03* 271 | X154813000Y-107431000D03* 272 | X152273000Y-107431000D03* 273 | X149733000Y-107431000D03* 274 | X147193000Y-107431000D03* 275 | X144653000Y-107431000D03* 276 | X142113000Y-107431000D03* 277 | X139573000Y-107431000D03* 278 | X137033000Y-107431000D03* 279 | X137033000Y-127011000D03* 280 | X139573000Y-127011000D03* 281 | X142113000Y-127011000D03* 282 | X144653000Y-127011000D03* 283 | X147193000Y-127011000D03* 284 | X149733000Y-127011000D03* 285 | X152273000Y-127011000D03* 286 | X154813000Y-127011000D03* 287 | X157353000Y-127011000D03* 288 | X159893000Y-127011000D03* 289 | X162433000Y-127011000D03* 290 | X164973000Y-127011000D03* 291 | X167513000Y-127011000D03* 292 | X170053000Y-127011000D03* 293 | X172593000Y-127011000D03* 294 | X175133000Y-127011000D03* 295 | X177673000Y-127011000D03* 296 | X180213000Y-127011000D03* 297 | X182753000Y-127011000D03* 298 | X185293000Y-127011000D03* 299 | D29* 300 | X113030000Y-133858000D03* 301 | X114300000Y-133858000D03* 302 | X111760000Y-133858000D03* 303 | D23* 304 | X125095000Y-125730000D03* 305 | X125095000Y-128270000D03* 306 | X125095000Y-130810000D03* 307 | X125095000Y-133350000D03* 308 | X132715000Y-133350000D03* 309 | X132715000Y-130810000D03* 310 | X132715000Y-128270000D03* 311 | X132715000Y-125730000D03* 312 | M02* 313 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem-F.Paste.gtp: -------------------------------------------------------------------------------- 1 | G04 #@! TF.FileFunction,Paste,Top* 2 | %FSLAX46Y46*% 3 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 4 | G04 Created by KiCad (PCBNEW 4.0.5+dfsg1-4) date Sat Oct 15 20:35:36 2022* 5 | %MOMM*% 6 | %LPD*% 7 | G01* 8 | G04 APERTURE LIST* 9 | %ADD10C,0.150000*% 10 | %ADD11R,2.000000X0.600000*% 11 | G04 APERTURE END LIST* 12 | D10* 13 | D11* 14 | X136905000Y-81661000D03* 15 | X136905000Y-82931000D03* 16 | X136905000Y-84201000D03* 17 | X136905000Y-85471000D03* 18 | X136905000Y-86741000D03* 19 | X136905000Y-88011000D03* 20 | X136905000Y-89281000D03* 21 | X136905000Y-90551000D03* 22 | X136905000Y-91821000D03* 23 | X136905000Y-93091000D03* 24 | X136905000Y-94361000D03* 25 | X136905000Y-95631000D03* 26 | X136905000Y-96901000D03* 27 | X136905000Y-98171000D03* 28 | X146305000Y-98171000D03* 29 | X146305000Y-96901000D03* 30 | X146305000Y-95631000D03* 31 | X146305000Y-94361000D03* 32 | X146305000Y-93091000D03* 33 | X146305000Y-91821000D03* 34 | X146305000Y-90551000D03* 35 | X146305000Y-89281000D03* 36 | X146305000Y-88011000D03* 37 | X146305000Y-86741000D03* 38 | X146305000Y-85471000D03* 39 | X146305000Y-84201000D03* 40 | X146305000Y-82931000D03* 41 | X146305000Y-81661000D03* 42 | M02* 43 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem-NPTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ;DRILL file {KiCad 4.0.5+dfsg1-4} date Sat Oct 15 20:35:42 2022 3 | ;FORMAT={-:-/ absolute / metric / decimal} 4 | FMAT,2 5 | METRIC,TZ 6 | T1C1.500 7 | T2C1.800 8 | T3C3.200 9 | % 10 | G90 11 | G05 12 | M71 13 | T1 14 | X182.133Y-114.796 15 | X182.133Y-119.646 16 | T2 17 | X185.163Y-114.496 18 | X185.163Y-119.946 19 | T3 20 | X119.45Y-85.77 21 | X119.45Y-132.02 22 | X159.45Y-85.77 23 | X159.45Y-132.02 24 | X189.45Y-85.77 25 | X189.45Y-132.02 26 | T0 27 | M30 28 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ;DRILL file {KiCad 4.0.5+dfsg1-4} date Sat Oct 15 20:35:42 2022 3 | ;FORMAT={-:-/ absolute / metric / decimal} 4 | FMAT,2 5 | METRIC,TZ 6 | T1C0.400 7 | T2C0.600 8 | T3C0.800 9 | T4C0.800 10 | T5C0.813 11 | T6C1.001 12 | T7C1.016 13 | T8C1.020 14 | T9C1.270 15 | % 16 | G90 17 | G05 18 | M71 19 | T1 20 | X111.76Y-136.398 21 | X130.429Y-125.73 22 | X130.429Y-136.398 23 | X131.826Y-86.741 24 | X131.826Y-99.441 25 | X132.461Y-88.011 26 | X132.461Y-98.171 27 | X133.096Y-89.281 28 | X133.096Y-101.981 29 | X133.731Y-90.551 30 | X133.731Y-96.901 31 | X134.366Y-91.821 32 | X134.366Y-100.711 33 | X135.001Y-93.218 34 | X135.001Y-103.632 35 | X137.033Y-134.366 36 | X142.748Y-84.201 37 | X142.748Y-98.171 38 | X147.193Y-136.271 39 | X149.987Y-86.741 40 | X149.987Y-98.171 41 | X156.083Y-88.011 42 | X156.083Y-97.028 43 | X161.036Y-91.821 44 | X161.036Y-99.441 45 | X162.433Y-91.821 46 | X162.433Y-95.631 47 | X164.973Y-85.217 48 | X164.973Y-94.234 49 | X167.767Y-86.741 50 | X167.767Y-90.551 51 | X170.053Y-81.661 52 | X170.053Y-93.091 53 | X171.323Y-90.551 54 | X171.323Y-98.171 55 | X172.593Y-89.281 56 | X172.593Y-94.361 57 | X177.673Y-99.441 58 | X178.562Y-86.741 59 | X178.562Y-104.775 60 | X179.578Y-89.281 61 | X179.578Y-103.886 62 | X182.753Y-104.775 63 | X185.293Y-103.886 64 | T2 65 | X111.76Y-133.858 66 | X113.03Y-133.858 67 | X114.3Y-133.858 68 | T3 69 | X111.76Y-138.176 70 | X125.095Y-125.73 71 | X125.095Y-128.27 72 | X125.095Y-130.81 73 | X125.095Y-133.35 74 | X129.286Y-82.042 75 | X132.715Y-125.73 76 | X132.715Y-128.27 77 | X132.715Y-130.81 78 | X132.715Y-133.35 79 | X133.858Y-85.471 80 | X142.748Y-78.359 81 | X149.733Y-84.582 82 | X153.162Y-80.772 83 | X174.879Y-79.121 84 | X174.879Y-81.661 85 | X174.879Y-84.201 86 | X174.879Y-86.741 87 | X174.879Y-89.281 88 | X174.879Y-91.821 89 | X174.879Y-94.361 90 | X174.879Y-96.901 91 | X174.879Y-99.441 92 | X174.879Y-101.981 93 | X182.499Y-79.121 94 | X182.499Y-81.661 95 | X182.499Y-84.201 96 | X182.499Y-86.741 97 | X182.499Y-89.281 98 | X182.499Y-91.821 99 | X182.499Y-94.361 100 | X182.499Y-96.901 101 | X182.499Y-99.441 102 | X182.499Y-101.981 103 | X186.182Y-78.359 104 | T4 105 | X114.26Y-138.176 106 | X129.286Y-84.542 107 | X133.858Y-82.971 108 | X140.248Y-78.359 109 | X149.733Y-82.082 110 | X153.162Y-85.852 111 | X186.182Y-80.859 112 | T5 113 | X139.573Y-131.572 114 | X139.573Y-134.366 115 | X147.193Y-131.572 116 | X147.193Y-134.366 117 | X195.045Y-84.516 118 | X195.045Y-91.12 119 | X195.045Y-97.724 120 | X195.045Y-104.328 121 | X195.045Y-110.932 122 | X195.045Y-117.536 123 | X195.045Y-124.14 124 | X195.045Y-130.744 125 | X202.665Y-84.516 126 | X202.665Y-91.12 127 | X202.665Y-97.724 128 | X202.665Y-104.328 129 | X202.665Y-110.932 130 | X202.665Y-117.536 131 | X202.665Y-124.14 132 | X202.665Y-130.744 133 | T6 134 | X182.753Y-133.099 135 | X205.74Y-84.516 136 | X205.74Y-87.056 137 | X205.74Y-91.12 138 | X205.74Y-93.66 139 | X205.74Y-97.724 140 | X205.74Y-100.264 141 | X205.74Y-104.328 142 | X205.74Y-106.868 143 | X205.74Y-110.932 144 | X205.74Y-113.472 145 | X205.74Y-117.536 146 | X205.74Y-120.076 147 | X205.74Y-124.14 148 | X205.74Y-126.68 149 | X205.74Y-130.744 150 | X205.74Y-133.284 151 | T7 152 | X126.365Y-91.805 153 | X126.365Y-94.345 154 | X126.365Y-96.885 155 | X126.365Y-99.425 156 | X126.365Y-101.965 157 | X128.905Y-91.805 158 | X128.905Y-94.345 159 | X128.905Y-96.885 160 | X128.905Y-99.425 161 | X128.905Y-101.965 162 | T8 163 | X137.033Y-108.331 164 | X137.033Y-126.111 165 | X139.573Y-108.331 166 | X139.573Y-126.111 167 | X142.113Y-108.331 168 | X142.113Y-126.111 169 | X144.653Y-108.331 170 | X144.653Y-126.111 171 | X147.193Y-108.331 172 | X147.193Y-126.111 173 | X149.733Y-108.331 174 | X149.733Y-126.111 175 | X152.273Y-108.331 176 | X152.273Y-126.111 177 | X154.813Y-108.331 178 | X154.813Y-126.111 179 | X155.563Y-117.805 180 | X155.563Y-120.345 181 | X155.563Y-122.885 182 | X157.353Y-108.331 183 | X157.353Y-126.111 184 | X159.893Y-108.331 185 | X159.893Y-126.111 186 | X162.433Y-108.331 187 | X162.433Y-126.111 188 | X164.973Y-108.331 189 | X164.973Y-126.111 190 | X167.513Y-108.331 191 | X167.513Y-126.111 192 | X170.053Y-108.331 193 | X170.053Y-126.111 194 | X172.593Y-108.331 195 | X172.593Y-126.111 196 | X175.133Y-108.331 197 | X175.133Y-126.111 198 | X177.673Y-108.331 199 | X177.673Y-126.111 200 | X180.213Y-108.331 201 | X180.213Y-126.111 202 | X182.753Y-108.331 203 | X182.753Y-126.111 204 | X185.293Y-108.331 205 | X185.293Y-126.111 206 | T9 207 | X172.593Y-133.099 208 | T6 209 | X113.611Y-121.231G85X113.611Y-123.229 210 | G05 211 | X115.611Y-126.929G85X117.61Y-126.929 212 | G05 213 | X119.61Y-121.231G85X119.61Y-123.229 214 | G05 215 | T0 216 | M30 217 | -------------------------------------------------------------------------------- /kicad/gerbers/Pico_Wifi_modem.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecparts/PicoWiFiModem/12148fc6f5a816a76dc473e19f7c6679ca7caa85/kicad/gerbers/Pico_Wifi_modem.zip -------------------------------------------------------------------------------- /kicad/library/Pico_Wifi_modem.lib: -------------------------------------------------------------------------------- 1 | EESchema-LIBRARY Version 2.3 2 | #encoding utf-8 3 | # 4 | # +3V3 5 | # 6 | DEF +3V3 #PWR 0 0 Y Y 1 F P 7 | F0 "#PWR" 0 -150 50 H I C CNN 8 | F1 "+3V3" 0 140 50 H V C CNN 9 | F2 "" 0 0 50 H V C CNN 10 | F3 "" 0 0 50 H V C CNN 11 | ALIAS +3.3V 12 | DRAW 13 | P 2 0 1 0 -30 50 0 100 N 14 | P 2 0 1 0 0 0 0 100 N 15 | P 2 0 1 0 0 100 30 50 N 16 | X +3V3 1 0 0 0 U 50 50 1 1 W N 17 | ENDDRAW 18 | ENDDEF 19 | # 20 | # +5V 21 | # 22 | DEF +5V #PWR 0 0 Y Y 1 F P 23 | F0 "#PWR" 0 -150 50 H I C CNN 24 | F1 "+5V" 0 140 50 H V C CNN 25 | F2 "" 0 0 50 H V C CNN 26 | F3 "" 0 0 50 H V C CNN 27 | DRAW 28 | P 2 0 1 0 -30 50 0 100 N 29 | P 2 0 1 0 0 0 0 100 N 30 | P 2 0 1 0 0 100 30 50 N 31 | X +5V 1 0 0 0 U 50 50 1 1 W N 32 | ENDDRAW 33 | ENDDEF 34 | # 35 | # 24LC16 36 | # 37 | DEF ~24LC16 U 0 30 Y Y 1 F N 38 | F0 "U" -250 250 50 H V C CNN 39 | F1 "24LC16" 200 250 50 H I C CNN 40 | F2 "DIP-8" 50 -250 50 H I L CNN 41 | F3 "" 0 -100 50 H V C CNN 42 | ALIAS 24LC00 24LC01 24LC02 24LC04 24LC08 24LC32 24LC64 24LC128 24LC256 24LC512 24LC1025 43 | $FPLIST 44 | SOIC* 45 | $ENDFPLIST 46 | DRAW 47 | X GND 4 0 -300 100 U 50 50 0 0 W 48 | X VCC 8 0 300 100 D 50 50 0 0 W 49 | S -300 200 300 -200 1 1 0 f 50 | X A0 1 -400 100 100 R 50 50 1 1 I 51 | X A1 2 -400 0 100 R 50 50 1 1 I 52 | X A2 3 -400 -100 100 R 50 50 1 1 I 53 | X SDA 5 400 -100 100 L 50 50 1 1 B 54 | X SCL 6 400 0 100 L 50 50 1 1 I 55 | X WP 7 400 100 100 L 50 50 1 1 I 56 | ENDDRAW 57 | ENDDEF 58 | # 59 | # 74LS245A 60 | # 61 | DEF 74LS245A U 0 10 Y Y 1 F N 62 | F0 "U" 100 575 50 H V L BNN 63 | F1 "74LS245A" 50 -575 50 H V L TNN 64 | F2 "" 0 0 50 H V C CNN 65 | F3 "" 0 0 50 H V C CNN 66 | ALIAS 74LS245 74HC245 67 | DRAW 68 | X GND 10 0 -650 100 U 50 50 0 0 W 69 | X VCC 20 0 650 100 D 50 50 0 0 W 70 | S -400 550 400 -550 0 1 0 f 71 | P 3 0 1 0 50 100 0 -100 -100 -100 N 72 | P 4 0 1 0 100 100 -50 100 -100 -100 -150 -100 N 73 | X A->B 1 -500 -400 100 R 50 50 1 1 I 74 | X A0 2 500 500 100 L 50 50 1 1 B 75 | X A1 3 500 400 100 L 50 50 1 1 B 76 | X A2 4 500 300 100 L 50 50 1 1 B 77 | X A3 5 500 200 100 L 50 50 1 1 B 78 | X A4 6 500 100 100 L 50 50 1 1 B 79 | X A5 7 500 0 100 L 50 50 1 1 B 80 | X A6 8 500 -100 100 L 50 50 1 1 B 81 | X A7 9 500 -200 100 L 50 50 1 1 B 82 | X B7 11 -500 -200 100 R 50 50 1 1 B 83 | X B6 12 -500 -100 100 R 50 50 1 1 B 84 | X B5 13 -500 0 100 R 50 50 1 1 B 85 | X B4 14 -500 100 100 R 50 50 1 1 B 86 | X B3 15 -500 200 100 R 50 50 1 1 B 87 | X B2 16 -500 300 100 R 50 50 1 1 B 88 | X B1 17 -500 400 100 R 50 50 1 1 B 89 | X B0 18 -500 500 100 R 50 50 1 1 B 90 | X CE 19 -500 -500 100 R 50 50 1 1 I I 91 | ENDDRAW 92 | ENDDEF 93 | # 94 | # BARREL_JACK 95 | # 96 | DEF BARREL_JACK CON 0 40 Y Y 1 F N 97 | F0 "CON" 0 250 50 H V C CNN 98 | F1 "BARREL_JACK" 0 -200 50 H V C CNN 99 | F2 "" 0 0 50 H V C CNN 100 | F3 "" 0 0 50 H V C CNN 101 | DRAW 102 | A -300 99 49 -900 1788 0 1 0 N -300 50 -350 100 103 | A -300 101 49 900 -1788 0 1 0 N -300 150 -350 100 104 | S 100 150 0 50 0 1 0 N 105 | P 2 0 1 0 -300 50 0 50 N 106 | P 2 0 1 0 0 150 -300 150 N 107 | P 3 0 1 0 100 0 -50 0 -50 -100 N 108 | P 5 0 1 0 100 -100 -150 -100 -200 -50 -250 -100 -350 -100 N 109 | X ~ 1 300 100 200 L 50 50 1 1 P 110 | X ~ 2 300 -100 200 L 50 50 1 1 P 111 | X ~ 3 300 0 200 L 50 50 1 1 P 112 | ENDDRAW 113 | ENDDEF 114 | # 115 | # CONN_02X05 116 | # 117 | DEF CONN_02X05 P 0 1 Y N 1 F N 118 | F0 "P" 0 300 50 H V C CNN 119 | F1 "CONN_02X05" 0 -300 50 H V C CNN 120 | F2 "" 0 -1200 50 H V C CNN 121 | F3 "" 0 -1200 50 H V C CNN 122 | $FPLIST 123 | Pin_Header_Straight_2X05 124 | Pin_Header_Angled_2X05 125 | Socket_Strip_Straight_2X05 126 | Socket_Strip_Angled_2X05 127 | $ENDFPLIST 128 | DRAW 129 | S -100 -195 -50 -205 0 1 0 N 130 | S -100 -95 -50 -105 0 1 0 N 131 | S -100 5 -50 -5 0 1 0 N 132 | S -100 105 -50 95 0 1 0 N 133 | S -100 205 -50 195 0 1 0 N 134 | S -100 250 100 -250 0 1 0 N 135 | S 50 -195 100 -205 0 1 0 N 136 | S 50 -95 100 -105 0 1 0 N 137 | S 50 5 100 -5 0 1 0 N 138 | S 50 105 100 95 0 1 0 N 139 | S 50 205 100 195 0 1 0 N 140 | X P1 1 -250 200 150 R 50 50 1 1 P 141 | X P2 2 250 200 150 L 50 50 1 1 P 142 | X P3 3 -250 100 150 R 50 50 1 1 P 143 | X P4 4 250 100 150 L 50 50 1 1 P 144 | X P5 5 -250 0 150 R 50 50 1 1 P 145 | X P6 6 250 0 150 L 50 50 1 1 P 146 | X P7 7 -250 -100 150 R 50 50 1 1 P 147 | X P8 8 250 -100 150 L 50 50 1 1 P 148 | X P9 9 -250 -200 150 R 50 50 1 1 P 149 | X P10 10 250 -200 150 L 50 50 1 1 P 150 | ENDDRAW 151 | ENDDEF 152 | # 153 | # C_Small 154 | # 155 | DEF C_Small C 0 10 N N 1 F N 156 | F0 "C" 10 70 50 H V L CNN 157 | F1 "C_Small" 10 -80 50 H V L CNN 158 | F2 "" 0 0 50 H V C CNN 159 | F3 "" 0 0 50 H V C CNN 160 | $FPLIST 161 | C? 162 | C_????_* 163 | C_???? 164 | SMD*_c 165 | Capacitor* 166 | $ENDFPLIST 167 | DRAW 168 | P 2 0 1 13 -60 -20 60 -20 N 169 | P 2 0 1 12 -60 20 60 20 N 170 | X ~ 1 0 100 80 D 50 50 1 1 P 171 | X ~ 2 0 -100 80 U 50 50 1 1 P 172 | ENDDRAW 173 | ENDDEF 174 | # 175 | # D 176 | # 177 | DEF D D 0 40 N N 1 F N 178 | F0 "D" 0 100 50 H V C CNN 179 | F1 "D" 0 -100 50 H V C CNN 180 | F2 "" 0 0 50 H V C CNN 181 | F3 "" 0 0 50 H V C CNN 182 | $FPLIST 183 | Diode_* 184 | D-* 185 | *SingleDiode 186 | *_Diode_* 187 | *SingleDiode* 188 | D_* 189 | $ENDFPLIST 190 | DRAW 191 | P 2 0 1 8 -25 25 -25 -25 N 192 | P 2 0 1 0 25 0 -25 0 N 193 | P 5 0 1 8 25 25 25 -25 -25 0 -25 0 25 25 N 194 | X K 1 -100 0 75 R 50 50 1 1 P 195 | X A 2 100 0 75 L 50 50 1 1 P 196 | ENDDRAW 197 | ENDDEF 198 | # 199 | # GND 200 | # 201 | DEF GND #PWR 0 0 Y Y 1 F P 202 | F0 "#PWR" 0 -250 50 H I C CNN 203 | F1 "GND" 0 -150 50 H V C CNN 204 | F2 "" 0 0 50 H V C CNN 205 | F3 "" 0 0 50 H V C CNN 206 | DRAW 207 | P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N 208 | X GND 1 0 0 0 D 50 50 1 1 W N 209 | ENDDRAW 210 | ENDDEF 211 | # 212 | # LED 213 | # 214 | DEF LED D 0 40 Y N 1 F N 215 | F0 "D" 0 100 50 H V C CNN 216 | F1 "LED" 0 -100 50 H V C CNN 217 | F2 "" 0 0 50 H V C CNN 218 | F3 "" 0 0 50 H V C CNN 219 | $FPLIST 220 | LED* 221 | $ENDFPLIST 222 | DRAW 223 | P 2 0 1 8 -50 -50 -50 50 N 224 | P 4 0 1 8 50 -50 50 50 -50 0 50 -50 N 225 | P 5 0 1 0 -120 -30 -180 -90 -150 -90 -180 -90 -180 -60 N 226 | P 5 0 1 0 -70 -30 -130 -90 -100 -90 -130 -90 -130 -60 N 227 | X K 1 -150 0 100 R 50 50 1 1 P 228 | X A 2 150 0 100 L 50 50 1 1 P 229 | ENDDRAW 230 | ENDDEF 231 | # 232 | # LM2931AZ-3.3/5.0 233 | # 234 | DEF LM2931AZ-3.3/5.0 U 0 30 Y Y 1 F N 235 | F0 "U" 0 250 50 H V C CNN 236 | F1 "LM2931AZ-3.3/5.0" 0 200 50 H V C CNN 237 | F2 "TO92-123" 0 100 50 H V C CIN 238 | F3 "" 0 0 50 H V C CNN 239 | ALIAS LM2931Z-3.3/5.0 240 | $FPLIST 241 | TO92-123 242 | $ENDFPLIST 243 | DRAW 244 | S -250 -150 250 150 0 1 10 f 245 | X VO 1 400 50 150 L 50 50 1 1 w 246 | X GND 2 0 -250 100 U 50 50 1 1 W 247 | X VI 3 -400 50 150 R 50 50 1 1 W 248 | ENDDRAW 249 | ENDDEF 250 | # 251 | # MAX3237CAI+ 252 | # 253 | DEF MAX3237CAI+ U 0 10 Y Y 1 L N 254 | F0 "U" -400 950 60 H V C CNN 255 | F1 "MAX3237CAI+" -350 850 60 H V C CNN 256 | F2 "21-0056C_28_MXM" -500 750 60 H I C CNN 257 | F3 "" -750 600 60 H V C CNN 258 | $FPLIST 259 | 21-0056C_28_MXM 260 | 21-0056C_28_MXM-M 261 | 21-0056C_28_MXM-L 262 | $ENDFPLIST 263 | DRAW 264 | S -450 700 450 -900 0 1 0 f 265 | X C2+ 1 -550 600 100 R 59 59 1 1 P 266 | X GND 2 0 -1000 100 U 59 59 1 1 W 267 | X C2- 3 -550 500 100 R 59 59 1 1 P 268 | X V- 4 -550 400 100 R 59 59 1 1 P 269 | X T1OUT 5 -550 200 100 R 59 59 1 1 O 270 | X T2OUT 6 -550 100 100 R 59 59 1 1 O 271 | X T3OUT 7 -550 0 100 R 59 59 1 1 O 272 | X R1IN 8 -550 -100 100 R 59 59 1 1 I 273 | X R2IN 9 -550 -200 100 R 59 59 1 1 I 274 | X T4OUT 10 -550 -300 100 R 59 59 1 1 O 275 | X R2OUT 20 550 -200 100 L 59 59 1 1 O 276 | X R3IN 11 -550 -400 100 R 59 59 1 1 I 277 | X R1OUT 21 550 -100 100 L 59 59 1 1 O 278 | X T5OUT 12 -550 -500 100 R 59 59 1 1 O 279 | X T3IN 22 550 0 100 L 59 59 1 1 I 280 | X EN 13 -550 -700 100 R 59 59 1 1 I I 281 | X T2IN 23 550 100 100 L 59 59 1 1 I 282 | X SHDN 14 -550 -800 100 R 59 59 1 1 I I 283 | X T1IN 24 550 200 100 L 59 59 1 1 I 284 | X MBAUD 15 550 -800 100 L 59 59 1 1 I 285 | X C1- 25 550 400 100 L 59 59 1 1 P 286 | X R1OUTB 16 550 -700 100 L 59 59 1 1 O 287 | X VCC 26 0 800 100 D 59 59 1 1 W 288 | X T5IN 17 550 -500 100 L 59 59 1 1 I 289 | X V+ 27 550 500 100 L 59 59 1 1 P 290 | X R3OUT 18 550 -400 100 L 59 59 1 1 O 291 | X C1+ 28 550 600 100 L 59 59 1 1 P 292 | X T4IN 19 550 -300 100 L 59 59 1 1 I 293 | ENDDRAW 294 | ENDDEF 295 | # 296 | # PWR_FLAG 297 | # 298 | DEF PWR_FLAG #FLG 0 0 N N 1 F P 299 | F0 "#FLG" 0 95 50 H I C CNN 300 | F1 "PWR_FLAG" 0 180 50 H V C CNN 301 | F2 "" 0 0 50 H V C CNN 302 | F3 "" 0 0 50 H V C CNN 303 | DRAW 304 | X pwr 1 0 0 0 U 50 50 0 0 w 305 | P 6 0 1 0 0 0 0 50 -75 100 0 150 75 100 0 50 N 306 | ENDDRAW 307 | ENDDEF 308 | # 309 | # Pico 310 | # 311 | DEF Pico U 0 40 Y Y 1 F N 312 | F0 "U" -550 1100 50 H V C CNN 313 | F1 "Pico" 0 750 50 H V C CNN 314 | F2 "RPi_Pico:RPi_Pico_SMD_TH" 0 0 50 V I C CNN 315 | F3 "" 0 0 50 H I C CNN 316 | DRAW 317 | T 0 0 850 50 0 0 0 Raspberry~Pi Normal 0 C C 318 | S -600 1050 600 -1050 0 1 0 f 319 | X GPIO0 1 -700 950 100 R 50 50 1 1 B 320 | X GPIO1 2 -700 850 100 R 50 50 1 1 B 321 | X GND 3 -700 750 100 R 50 50 1 1 W 322 | X GPIO2 4 -700 650 100 R 50 50 1 1 B 323 | X GPIO3 5 -700 550 100 R 50 50 1 1 B 324 | X GPIO4 6 -700 450 100 R 50 50 1 1 B 325 | X GPIO5 7 -700 350 100 R 50 50 1 1 B 326 | X GND 8 -700 250 100 R 50 50 1 1 W 327 | X GPIO6 9 -700 150 100 R 50 50 1 1 B 328 | X GPIO7 10 -700 50 100 R 50 50 1 1 B 329 | X GPIO15 20 -700 -950 100 R 50 50 1 1 B 330 | X RUN 30 700 -50 100 L 50 50 1 1 I 331 | X VBUS 40 700 950 100 L 50 50 1 1 P 332 | X GPIO8 11 -700 -50 100 R 50 50 1 1 B 333 | X GPIO16 21 700 -950 100 L 50 50 1 1 B 334 | X GPIO26_ADC0 31 700 50 100 L 50 50 1 1 B 335 | X SWCLK 41 -100 -1150 100 U 50 50 1 1 I 336 | X GPIO9 12 -700 -150 100 R 50 50 1 1 B 337 | X GPIO17 22 700 -850 100 L 50 50 1 1 B 338 | X GPIO27_ADC1 32 700 150 100 L 50 50 1 1 B 339 | X GND 42 0 -1150 100 U 50 50 1 1 W 340 | X GND 13 -700 -250 100 R 50 50 1 1 W 341 | X GND 23 700 -750 100 L 50 50 1 1 W 342 | X AGND 33 700 250 100 L 50 50 1 1 W 343 | X SWDIO 43 100 -1150 100 U 50 50 1 1 B 344 | X GPIO10 14 -700 -350 100 R 50 50 1 1 B 345 | X GPIO18 24 700 -650 100 L 50 50 1 1 B 346 | X GPIO28_ADC2 34 700 350 100 L 50 50 1 1 B 347 | X GPIO11 15 -700 -450 100 R 50 50 1 1 B 348 | X GPIO19 25 700 -550 100 L 50 50 1 1 B 349 | X ADC_VREF 35 700 450 100 L 50 50 1 1 P 350 | X GPIO12 16 -700 -550 100 R 50 50 1 1 B 351 | X GPIO20 26 700 -450 100 L 50 50 1 1 B 352 | X 3V3 36 700 550 100 L 50 50 1 1 w 353 | X GPIO13 17 -700 -650 100 R 50 50 1 1 B 354 | X GPIO21 27 700 -350 100 L 50 50 1 1 B 355 | X 3V3_EN 37 700 650 100 L 50 50 1 1 I 356 | X GND 18 -700 -750 100 R 50 50 1 1 W 357 | X GND 28 700 -250 100 L 50 50 1 1 W 358 | X GND 38 700 750 100 L 50 50 1 1 W 359 | X GPIO14 19 -700 -850 100 R 50 50 1 1 B 360 | X GPIO22 29 700 -150 100 L 50 50 1 1 B 361 | X VSYS 39 700 850 100 L 50 50 1 1 P 362 | ENDDRAW 363 | ENDDEF 364 | # 365 | # R_US 366 | # 367 | DEF R_US R 0 40 N N 1 F N 368 | F0 "R" 80 0 50 V V C CNN 369 | F1 "R_US" -80 0 50 V V C CNN 370 | F2 "Discret:R3-LARGE_PADS" 0 150 60 H I C CNN 371 | F3 "" 0 0 60 H I C CNN 372 | $FPLIST 373 | R? 374 | R_* 375 | $ENDFPLIST 376 | DRAW 377 | P 10 0 1 10 0 -70 0 -60 -30 -50 30 -30 -30 -10 30 10 -30 30 30 50 0 60 0 70 N 378 | X ~ 1 0 100 25 D 40 40 1 1 P 379 | X ~ 2 0 -100 25 U 40 40 1 1 P 380 | ENDDRAW 381 | ENDDEF 382 | # 383 | #End Library 384 | -------------------------------------------------------------------------------- /kicad/modules.pretty/BARREL_JACK.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Connectors:BARREL_JACK locked (layer F.Cu) (tedit 633E1C44) 2 | (descr "DC Barrel Jack") 3 | (tags "Power Jack") 4 | (fp_text reference CON1 (at -1.269 6.421 180) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value BARREL_JACK (at 2.033 -6.152) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -4.0005 -4.50088) (end -4.0005 4.50088) (layer F.SilkS) (width 0.15)) 11 | (fp_line (start -7.50062 -4.50088) (end -7.50062 4.50088) (layer F.SilkS) (width 0.15)) 12 | (fp_line (start -7.50062 4.50088) (end 7.00024 4.50088) (layer F.SilkS) (width 0.15)) 13 | (fp_line (start 7.00024 4.50088) (end 7.00024 -4.50088) (layer F.SilkS) (width 0.15)) 14 | (fp_line (start 7.00024 -4.50088) (end -7.50062 -4.50088) (layer F.SilkS) (width 0.15)) 15 | (pad 1 thru_hole rect (at 6.20014 0) (size 3.50012 3.50012) (drill oval 1 3) (layers *.Cu *.Mask)) 16 | (pad 2 thru_hole rect (at 0.20066 0) (size 3.50012 3.50012) (drill oval 1 3) (layers *.Cu *.Mask)) 17 | (pad 3 thru_hole rect (at 3.2004 4.699) (size 3.50012 3.50012) (drill oval 3 1) (layers *.Cu *.Mask)) 18 | ) 19 | -------------------------------------------------------------------------------- /kicad/modules.pretty/C_Disc_D3_P2.5.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Capacitors_THT:C_Disc_D3_P2.5 (layer F.Cu) (tedit 633E75D6) 2 | (descr "Capacitor 3mm Disc, Pitch 2.5mm") 3 | (tags Capacitor) 4 | (fp_text reference C7 (at 4.445 -0.127 90) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value 1uF (at 1.25 2.5) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -0.9 -1.5) (end 3.4 -1.5) (layer F.CrtYd) (width 0.05)) 11 | (fp_line (start 3.4 -1.5) (end 3.4 1.5) (layer F.CrtYd) (width 0.05)) 12 | (fp_line (start 3.4 1.5) (end -0.9 1.5) (layer F.CrtYd) (width 0.05)) 13 | (fp_line (start -0.9 1.5) (end -0.9 -1.5) (layer F.CrtYd) (width 0.05)) 14 | (fp_line (start -0.25 -1.25) (end 2.75 -1.25) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start 2.75 1.25) (end -0.25 1.25) (layer F.SilkS) (width 0.15)) 16 | (pad 1 thru_hole rect (at 0 0) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 17 | (pad 2 thru_hole circle (at 2.5 0) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 18 | (model Capacitors_ThroughHole.3dshapes/C_Disc_D3_P2.5.wrl 19 | (at (xyz 0.0492126 0 0)) 20 | (scale (xyz 1 1 1)) 21 | (rotate (xyz 0 0 0)) 22 | ) 23 | ) 24 | -------------------------------------------------------------------------------- /kicad/modules.pretty/C_Disc_D3_P5.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Capacitors_THT:C_Disc_D3_P5 (layer F.Cu) (tedit 633E2480) 2 | (descr "Capacitor 3mm Disc, Pitch 5.08mm") 3 | (tags Capacitor) 4 | (fp_text reference C6 (at -4.191 0.254 90) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value 100nF (at 0 2.5) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -3.42 -1.5) (end 3.42 -1.5) (layer F.CrtYd) (width 0.05)) 11 | (fp_line (start 3.42 -1.5) (end 3.42 1.5) (layer F.CrtYd) (width 0.05)) 12 | (fp_line (start 3.42 1.5) (end -3.42 1.5) (layer F.CrtYd) (width 0.05)) 13 | (fp_line (start -3.42 1.5) (end -3.42 -1.5) (layer F.CrtYd) (width 0.05)) 14 | (fp_line (start -2.77 -1.25) (end 2.77 -1.25) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start 2.77 1.25) (end -2.77 1.25) (layer F.SilkS) (width 0.15)) 16 | (pad 1 thru_hole rect (at -2.54 0) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 17 | (pad 2 thru_hole circle (at 2.54 0) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 18 | ) 19 | -------------------------------------------------------------------------------- /kicad/modules.pretty/DIP-20_W7.62mm_LongPads.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Housings_DIP:DIP-20_W7.62mm_LongPads locked (layer F.Cu) (tedit 633E456C) 2 | (descr "20-lead dip package, row spacing 7.62 mm (300 mils), longer pads") 3 | (tags "dil dip 2.54 300") 4 | (fp_text reference U2 (at -2.921 -1.651 180) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value 74HCT245 (at -2.413 3.048 270) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -1.4 -2.45) (end -1.4 25.35) (layer F.CrtYd) (width 0.05)) 11 | (fp_line (start 9 -2.45) (end 9 25.35) (layer F.CrtYd) (width 0.05)) 12 | (fp_line (start -1.4 -2.45) (end 9 -2.45) (layer F.CrtYd) (width 0.05)) 13 | (fp_line (start -1.4 25.35) (end 9 25.35) (layer F.CrtYd) (width 0.05)) 14 | (fp_line (start 0.135 -2.295) (end 0.135 -1.025) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start 7.485 -2.295) (end 7.485 -1.025) (layer F.SilkS) (width 0.15)) 16 | (fp_line (start 7.485 25.155) (end 7.485 23.885) (layer F.SilkS) (width 0.15)) 17 | (fp_line (start 0.135 25.155) (end 0.135 23.885) (layer F.SilkS) (width 0.15)) 18 | (fp_line (start 0.135 -2.295) (end 7.485 -2.295) (layer F.SilkS) (width 0.15)) 19 | (fp_line (start 0.135 25.155) (end 7.485 25.155) (layer F.SilkS) (width 0.15)) 20 | (fp_line (start 0.135 -1.025) (end -1.15 -1.025) (layer F.SilkS) (width 0.15)) 21 | (pad 1 thru_hole oval (at 0 0 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 22 | (pad 2 thru_hole oval (at 0 2.54 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 23 | (pad 3 thru_hole oval (at 0 5.08 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 24 | (pad 4 thru_hole oval (at 0 7.62 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 25 | (pad 5 thru_hole oval (at 0 10.16 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 26 | (pad 6 thru_hole oval (at 0 12.7 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 27 | (pad 7 thru_hole oval (at 0 15.24 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 28 | (pad 8 thru_hole oval (at 0 17.78 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 29 | (pad 9 thru_hole oval (at 0 20.32 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 30 | (pad 10 thru_hole oval (at 0 22.86 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 31 | (pad 11 thru_hole oval (at 7.62 22.86 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 32 | (pad 12 thru_hole oval (at 7.62 20.32 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 33 | (pad 13 thru_hole oval (at 7.62 17.78 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 34 | (pad 14 thru_hole oval (at 7.62 15.24 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 35 | (pad 15 thru_hole oval (at 7.62 12.7 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 36 | (pad 16 thru_hole oval (at 7.62 10.16 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 37 | (pad 17 thru_hole oval (at 7.62 7.62 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 38 | (pad 18 thru_hole oval (at 7.62 5.08 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 39 | (pad 19 thru_hole oval (at 7.62 2.54 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 40 | (pad 20 thru_hole oval (at 7.62 0 180) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 41 | (model Housings_DIP.3dshapes/DIP-20_W7.62mm_LongPads.wrl 42 | (at (xyz 0 0 0)) 43 | (scale (xyz 1 1 1)) 44 | (rotate (xyz 0 0 0)) 45 | ) 46 | ) 47 | -------------------------------------------------------------------------------- /kicad/modules.pretty/DIP-8_W7.62mm_LongPads.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Housings_DIP:DIP-8_W7.62mm_LongPads (layer F.Cu) (tedit 633E75C8) 2 | (descr "8-lead dip package, row spacing 7.62 mm (300 mils), longer pads") 3 | (tags "dil dip 2.54 300") 4 | (fp_text reference U5 (at 6.35 -3.556 180) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value 24LC32 (at 3.683 11.684) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -1.4 -2.45) (end -1.4 10.1) (layer F.CrtYd) (width 0.05)) 11 | (fp_line (start 9 -2.45) (end 9 10.1) (layer F.CrtYd) (width 0.05)) 12 | (fp_line (start -1.4 -2.45) (end 9 -2.45) (layer F.CrtYd) (width 0.05)) 13 | (fp_line (start -1.4 10.1) (end 9 10.1) (layer F.CrtYd) (width 0.05)) 14 | (fp_line (start 0.135 -2.295) (end 0.135 -1.025) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start 7.485 -2.295) (end 7.485 -1.025) (layer F.SilkS) (width 0.15)) 16 | (fp_line (start 7.485 9.915) (end 7.485 8.645) (layer F.SilkS) (width 0.15)) 17 | (fp_line (start 0.135 9.915) (end 0.135 8.645) (layer F.SilkS) (width 0.15)) 18 | (fp_line (start 0.135 -2.295) (end 7.485 -2.295) (layer F.SilkS) (width 0.15)) 19 | (fp_line (start 0.135 9.915) (end 7.485 9.915) (layer F.SilkS) (width 0.15)) 20 | (fp_line (start 0.135 -1.025) (end -1.15 -1.025) (layer F.SilkS) (width 0.15)) 21 | (pad 1 thru_hole oval (at 0 0) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 22 | (pad 2 thru_hole oval (at 0 2.54) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 23 | (pad 3 thru_hole oval (at 0 5.08) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 24 | (pad 4 thru_hole oval (at 0 7.62) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 25 | (pad 5 thru_hole oval (at 7.62 7.62) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 26 | (pad 6 thru_hole oval (at 7.62 5.08) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 27 | (pad 7 thru_hole oval (at 7.62 2.54) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 28 | (pad 8 thru_hole oval (at 7.62 0) (size 2.3 1.6) (drill 0.8) (layers *.Cu *.Mask)) 29 | (model Housings_DIP.3dshapes/DIP-8_W7.62mm_LongPads.wrl 30 | (at (xyz 0 0 0)) 31 | (scale (xyz 1 1 1)) 32 | (rotate (xyz 0 0 0)) 33 | ) 34 | ) 35 | -------------------------------------------------------------------------------- /kicad/modules.pretty/Diode_DO-41_SOD81_Horizontal_RM10.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Diodes_THT:Diode_DO-41_SOD81_Horizontal_RM10 (layer F.Cu) (tedit 633E1C52) 2 | (descr "Diode, DO-41, SOD81, Horizontal, RM 10mm,") 3 | (tags "Diode, DO-41, SOD81, Horizontal, RM 10mm, 1N4007, SB140,") 4 | (fp_text reference D12 (at 5.334 -2.159) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value 1N5817 (at 4.37134 -3.55854) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start 7.62 -0.00254) (end 8.636 -0.00254) (layer F.SilkS) (width 0.15)) 11 | (fp_line (start 2.794 -0.00254) (end 1.524 -0.00254) (layer F.SilkS) (width 0.15)) 12 | (fp_line (start 3.048 -1.27254) (end 3.048 1.26746) (layer F.SilkS) (width 0.15)) 13 | (fp_line (start 3.302 -1.27254) (end 3.302 1.26746) (layer F.SilkS) (width 0.15)) 14 | (fp_line (start 3.556 -1.27254) (end 3.556 1.26746) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start 2.794 -1.27254) (end 2.794 1.26746) (layer F.SilkS) (width 0.15)) 16 | (fp_line (start 3.81 -1.27254) (end 2.54 1.26746) (layer F.SilkS) (width 0.15)) 17 | (fp_line (start 2.54 -1.27254) (end 3.81 1.26746) (layer F.SilkS) (width 0.15)) 18 | (fp_line (start 3.81 -1.27254) (end 3.81 1.26746) (layer F.SilkS) (width 0.15)) 19 | (fp_line (start 3.175 -1.27254) (end 3.175 1.26746) (layer F.SilkS) (width 0.15)) 20 | (fp_line (start 2.54 1.26746) (end 2.54 -1.27254) (layer F.SilkS) (width 0.15)) 21 | (fp_line (start 2.54 -1.27254) (end 7.62 -1.27254) (layer F.SilkS) (width 0.15)) 22 | (fp_line (start 7.62 -1.27254) (end 7.62 1.26746) (layer F.SilkS) (width 0.15)) 23 | (fp_line (start 7.62 1.26746) (end 2.54 1.26746) (layer F.SilkS) (width 0.15)) 24 | (pad 2 thru_hole circle (at 10.16 -0.00254 180) (size 2 2) (drill 1) (layers *.Cu *.Mask)) 25 | (pad 1 thru_hole rect (at 0 -0.00254 180) (size 2 2) (drill 1) (layers *.Cu *.Mask)) 26 | ) 27 | -------------------------------------------------------------------------------- /kicad/modules.pretty/IDC_Header_Straight_10pins.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Connectors:IDC_Header_Straight_10pins locked (layer F.Cu) (tedit 633E017C) 2 | (descr "10 pins through hole IDC header") 3 | (tags "IDC header socket VASCH") 4 | (fp_text reference P1 (at 5.08 -7.62 270) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value CONN_02X05 (at 11.795 -7.366) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -5.08 -5.82) (end 15.24 -5.82) (layer F.SilkS) (width 0.15)) 11 | (fp_line (start -4.54 -5.27) (end 14.68 -5.27) (layer F.SilkS) (width 0.15)) 12 | (fp_line (start -5.08 3.28) (end 15.24 3.28) (layer F.SilkS) (width 0.15)) 13 | (fp_line (start -4.54 2.73) (end 2.83 2.73) (layer F.SilkS) (width 0.15)) 14 | (fp_line (start 7.33 2.73) (end 14.68 2.73) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start 2.83 2.73) (end 2.83 3.28) (layer F.SilkS) (width 0.15)) 16 | (fp_line (start 7.33 2.73) (end 7.33 3.28) (layer F.SilkS) (width 0.15)) 17 | (fp_line (start -5.08 -5.82) (end -5.08 3.28) (layer F.SilkS) (width 0.15)) 18 | (fp_line (start -4.54 -5.27) (end -4.54 2.73) (layer F.SilkS) (width 0.15)) 19 | (fp_line (start 15.24 -5.82) (end 15.24 3.28) (layer F.SilkS) (width 0.15)) 20 | (fp_line (start 14.68 -5.27) (end 14.68 2.73) (layer F.SilkS) (width 0.15)) 21 | (fp_line (start -5.08 -5.82) (end -4.54 -5.27) (layer F.SilkS) (width 0.15)) 22 | (fp_line (start 15.24 -5.82) (end 14.68 -5.27) (layer F.SilkS) (width 0.15)) 23 | (fp_line (start -5.08 3.28) (end -4.54 2.73) (layer F.SilkS) (width 0.15)) 24 | (fp_line (start 15.24 3.28) (end 14.68 2.73) (layer F.SilkS) (width 0.15)) 25 | (fp_line (start -5.35 -6.05) (end 15.5 -6.05) (layer F.CrtYd) (width 0.05)) 26 | (fp_line (start 15.5 -6.05) (end 15.5 3.55) (layer F.CrtYd) (width 0.05)) 27 | (fp_line (start 15.5 3.55) (end -5.35 3.55) (layer F.CrtYd) (width 0.05)) 28 | (fp_line (start -5.35 3.55) (end -5.35 -6.05) (layer F.CrtYd) (width 0.05)) 29 | (pad 1 thru_hole rect (at 0 0 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 30 | (pad 2 thru_hole oval (at 0 -2.54 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 31 | (pad 3 thru_hole oval (at 2.54 0 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 32 | (pad 4 thru_hole oval (at 2.54 -2.54 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 33 | (pad 5 thru_hole oval (at 5.08 0 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 34 | (pad 6 thru_hole oval (at 5.08 -2.54 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 35 | (pad 7 thru_hole oval (at 7.62 0 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 36 | (pad 8 thru_hole oval (at 7.62 -2.54 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 37 | (pad 9 thru_hole oval (at 10.16 0 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 38 | (pad 10 thru_hole oval (at 10.16 -2.54 270) (size 1.7272 1.7272) (drill 1) (layers *.Cu *.Mask)) 39 | ) 40 | -------------------------------------------------------------------------------- /kicad/modules.pretty/LED-3MM.kicad_mod: -------------------------------------------------------------------------------- 1 | (module LEDs:LED-3MM locked (layer F.Cu) (tedit 633E16BA) 2 | (descr "LED 3mm round vertical") 3 | (tags "LED 3mm round vertical") 4 | (fp_text reference D8 (at 1.91 3.06 90) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value TLPR5600 (at 3.495 6.096 90) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -1.2 2.3) (end 3.8 2.3) (layer F.CrtYd) (width 0.05)) 11 | (fp_line (start 3.8 2.3) (end 3.8 -2.2) (layer F.CrtYd) (width 0.05)) 12 | (fp_line (start 3.8 -2.2) (end -1.2 -2.2) (layer F.CrtYd) (width 0.05)) 13 | (fp_line (start -1.2 -2.2) (end -1.2 2.3) (layer F.CrtYd) (width 0.05)) 14 | (fp_line (start -0.199 1.314) (end -0.199 1.114) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start -0.199 -1.28) (end -0.199 -1.1) (layer F.SilkS) (width 0.15)) 16 | (fp_arc (start 1.301 0.034) (end -0.199 -1.286) (angle 108.5) (layer F.SilkS) (width 0.15)) 17 | (fp_arc (start 1.301 0.034) (end 0.25 -1.1) (angle 85.7) (layer F.SilkS) (width 0.15)) 18 | (fp_arc (start 1.311 0.034) (end 3.051 0.994) (angle 110) (layer F.SilkS) (width 0.15)) 19 | (fp_arc (start 1.301 0.034) (end 2.335 1.094) (angle 87.5) (layer F.SilkS) (width 0.15)) 20 | (fp_text user K (at -1.69 1.74 90) (layer F.SilkS) 21 | (effects (font (size 1 1) (thickness 0.15))) 22 | ) 23 | (pad 1 thru_hole rect (at 0 0 180) (size 2 2) (drill 1) (layers *.Cu *.Mask)) 24 | (pad 2 thru_hole circle (at 2.54 0 90) (size 2 2) (drill 1) (layers *.Cu *.Mask)) 25 | (model LEDs.3dshapes/LED-3MM.wrl 26 | (at (xyz 0.05 0 0)) 27 | (scale (xyz 1 1 1)) 28 | (rotate (xyz 0 0 90)) 29 | ) 30 | ) 31 | -------------------------------------------------------------------------------- /kicad/modules.pretty/MountingHole_3.2mm_Hammond_1593.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Mounting_Holes:MountingHole_3.2mm_Hammond_1593 locked (layer F.Cu) (tedit 5E753046) 2 | (descr "Mounting Hole 3.2mm, no annular, Hammond 1593") 3 | (tags "mounting hole 3.2mm no annular Hammond 1593") 4 | (fp_text reference "" (at 0 -4.2) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value "" (at 0 4.2) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_circle (center 0 0) (end 2.71 0) (layer Cmts.User) (width 0.15)) 11 | (fp_circle (center 0 0) (end 2.96 0) (layer F.CrtYd) (width 0.05)) 12 | (pad 1 np_thru_hole circle (at 0 0) (size 3.2 3.2) (drill 3.2) (layers *.Cu *.Mask)) 13 | ) 14 | -------------------------------------------------------------------------------- /kicad/modules.pretty/R3.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Discret:R3 (layer F.Cu) (tedit 0) 2 | (descr "Resitance 3 pas") 3 | (tags R) 4 | (fp_text reference R13 (at 0 0.127) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value 3.9K (at 0 0.127) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -3.81 0) (end -3.302 0) (layer F.SilkS) (width 0.15)) 11 | (fp_line (start 3.81 0) (end 3.302 0) (layer F.SilkS) (width 0.15)) 12 | (fp_line (start 3.302 0) (end 3.302 -1.016) (layer F.SilkS) (width 0.15)) 13 | (fp_line (start 3.302 -1.016) (end -3.302 -1.016) (layer F.SilkS) (width 0.15)) 14 | (fp_line (start -3.302 -1.016) (end -3.302 1.016) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start -3.302 1.016) (end 3.302 1.016) (layer F.SilkS) (width 0.15)) 16 | (fp_line (start 3.302 1.016) (end 3.302 0) (layer F.SilkS) (width 0.15)) 17 | (fp_line (start -3.302 -0.508) (end -2.794 -1.016) (layer F.SilkS) (width 0.15)) 18 | (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8) (layers *.Cu *.Mask)) 19 | (pad 2 thru_hole circle (at 3.81 0) (size 1.397 1.397) (drill 0.8) (layers *.Cu *.Mask)) 20 | (model Discret.3dshapes/R3.wrl 21 | (at (xyz 0 0 0)) 22 | (scale (xyz 0.3 0.3 0.3)) 23 | (rotate (xyz 0 0 0)) 24 | ) 25 | ) 26 | -------------------------------------------------------------------------------- /kicad/modules.pretty/RPi_PicoW.kicad_mod: -------------------------------------------------------------------------------- 1 | (module RPi_PicoW (layer F.Cu) (tedit 633F045B) 2 | (descr "Through hole straight pin header, 2x20, 2.54mm pitch, double rows") 3 | (tags "Through hole pin header THT 2x20 2.54mm double row") 4 | (fp_text reference U3 (at 0 0) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value Pico (at 0 2.159) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start 1.1 25.5) (end 1.5 25.5) (layer F.SilkS) (width 0.12)) 11 | (fp_line (start 10.5 -12.9) (end 10.5 -12.5) (layer F.SilkS) (width 0.12)) 12 | (fp_line (start 10.5 -15.4) (end 10.5 -15) (layer F.SilkS) (width 0.12)) 13 | (fp_line (start -10.5 12.5) (end -10.5 12.9) (layer F.SilkS) (width 0.12)) 14 | (fp_line (start 10.5 10) (end 10.5 10.4) (layer F.SilkS) (width 0.12)) 15 | (fp_line (start -10.5 2.3) (end -10.5 2.7) (layer F.SilkS) (width 0.12)) 16 | (fp_line (start 10.5 4.9) (end 10.5 5.3) (layer F.SilkS) (width 0.12)) 17 | (fp_line (start 10.5 2.3) (end 10.5 2.7) (layer F.SilkS) (width 0.12)) 18 | (fp_line (start 10.5 25.5) (end 3.7 25.5) (layer F.SilkS) (width 0.12)) 19 | (fp_line (start -10.5 10) (end -10.5 10.4) (layer F.SilkS) (width 0.12)) 20 | (fp_line (start -10.5 4.9) (end -10.5 5.3) (layer F.SilkS) (width 0.12)) 21 | (fp_line (start 10.5 -20.5) (end 10.5 -20.1) (layer F.SilkS) (width 0.12)) 22 | (fp_line (start -1.5 25.5) (end -1.1 25.5) (layer F.SilkS) (width 0.12)) 23 | (fp_line (start 10.5 20.1) (end 10.5 20.5) (layer F.SilkS) (width 0.12)) 24 | (fp_line (start -10.5 -23.1) (end -10.5 -22.7) (layer F.SilkS) (width 0.12)) 25 | (fp_line (start 10.5 15.1) (end 10.5 15.5) (layer F.SilkS) (width 0.12)) 26 | (fp_line (start 10.5 -5.3) (end 10.5 -4.9) (layer F.SilkS) (width 0.12)) 27 | (fp_line (start -10.5 -0.2) (end -10.5 0.2) (layer F.SilkS) (width 0.12)) 28 | (fp_line (start -10.5 -20.5) (end -10.5 -20.1) (layer F.SilkS) (width 0.12)) 29 | (fp_line (start -10.5 20.1) (end -10.5 20.5) (layer F.SilkS) (width 0.12)) 30 | (fp_line (start 10.5 12.5) (end 10.5 12.9) (layer F.SilkS) (width 0.12)) 31 | (fp_line (start -10.5 -12.9) (end -10.5 -12.5) (layer F.SilkS) (width 0.12)) 32 | (fp_line (start 10.5 -23.1) (end 10.5 -22.7) (layer F.SilkS) (width 0.12)) 33 | (fp_line (start -10.5 -2.7) (end -10.5 -2.3) (layer F.SilkS) (width 0.12)) 34 | (fp_line (start 10.5 -0.2) (end 10.5 0.2) (layer F.SilkS) (width 0.12)) 35 | (fp_line (start -10.5 -10.4) (end -10.5 -10) (layer F.SilkS) (width 0.12)) 36 | (fp_line (start 10.5 -2.7) (end 10.5 -2.3) (layer F.SilkS) (width 0.12)) 37 | (fp_line (start 10.5 7.4) (end 10.5 7.8) (layer F.SilkS) (width 0.12)) 38 | (fp_line (start -10.5 -18) (end -10.5 -17.6) (layer F.SilkS) (width 0.12)) 39 | (fp_line (start 10.5 -7.8) (end 10.5 -7.4) (layer F.SilkS) (width 0.12)) 40 | (fp_line (start -3.7 25.5) (end -10.5 25.5) (layer F.SilkS) (width 0.12)) 41 | (fp_line (start -10.5 -7.8) (end -10.5 -7.4) (layer F.SilkS) (width 0.12)) 42 | (fp_line (start -10.5 22.7) (end -10.5 23.1) (layer F.SilkS) (width 0.12)) 43 | (fp_line (start 10.5 17.6) (end 10.5 18) (layer F.SilkS) (width 0.12)) 44 | (fp_line (start -10.5 -25.5) (end 10.5 -25.5) (layer F.SilkS) (width 0.12)) 45 | (fp_line (start -10.5 -15.4) (end -10.5 -15) (layer F.SilkS) (width 0.12)) 46 | (fp_line (start 10.5 -10.4) (end 10.5 -10) (layer F.SilkS) (width 0.12)) 47 | (fp_line (start -7.493 -22.833) (end -7.493 -25.5) (layer F.SilkS) (width 0.12)) 48 | (fp_line (start 10.5 22.7) (end 10.5 23.1) (layer F.SilkS) (width 0.12)) 49 | (fp_line (start 10.5 -18) (end 10.5 -17.6) (layer F.SilkS) (width 0.12)) 50 | (fp_line (start -10.5 15.1) (end -10.5 15.5) (layer F.SilkS) (width 0.12)) 51 | (fp_line (start -10.5 -22.833) (end -7.493 -22.833) (layer F.SilkS) (width 0.12)) 52 | (fp_line (start 10.5 -25.5) (end 10.5 -25.2) (layer F.SilkS) (width 0.12)) 53 | (fp_line (start -10.5 -5.3) (end -10.5 -4.9) (layer F.SilkS) (width 0.12)) 54 | (fp_line (start -10.5 -25.5) (end -10.5 -25.2) (layer F.SilkS) (width 0.12)) 55 | (fp_line (start -10.5 17.6) (end -10.5 18) (layer F.SilkS) (width 0.12)) 56 | (fp_line (start -10.5 7.4) (end -10.5 7.8) (layer F.SilkS) (width 0.12)) 57 | (fp_line (start -7.1 25.5) (end -7.1 17) (layer Dwgs.User) (width 0.12)) 58 | (fp_line (start -7.1 17) (end 7.1 17) (layer Dwgs.User) (width 0.12)) 59 | (fp_line (start 7.1 17) (end 7.1 25.5) (layer Dwgs.User) (width 0.12)) 60 | (fp_text user %R (at 0 0 180) (layer F.Fab) 61 | (effects (font (size 1 1) (thickness 0.15))) 62 | ) 63 | (fp_poly (pts (xy -1.5 -9.9) (xy -3.5 -9.9) (xy -3.5 -11.9) (xy -1.5 -11.9)) (layer Dwgs.User) (width 0.1)) 64 | (fp_poly (pts (xy 3.7 -20.2) (xy -3.7 -20.2) (xy -3.7 -24.9) (xy 3.7 -24.9)) (layer Dwgs.User) (width 0.1)) 65 | (fp_poly (pts (xy -1.5 -14.9) (xy -3.5 -14.9) (xy -3.5 -16.9) (xy -1.5 -16.9)) (layer Dwgs.User) (width 0.1)) 66 | (fp_poly (pts (xy -1.5 -12.4) (xy -3.5 -12.4) (xy -3.5 -14.4) (xy -1.5 -14.4)) (layer Dwgs.User) (width 0.1)) 67 | (fp_text user "Copper Keepouts shown on Dwgs layer" (at 0.1 -30.2) (layer Cmts.User) 68 | (effects (font (size 1 1) (thickness 0.15))) 69 | ) 70 | (fp_line (start 11 26) (end -11 26) (layer F.CrtYd) (width 0.12)) 71 | (fp_line (start -11 26) (end -11 -26) (layer F.CrtYd) (width 0.12)) 72 | (fp_line (start 11 -26) (end 11 26) (layer F.CrtYd) (width 0.12)) 73 | (fp_line (start -11 -26) (end 11 -26) (layer F.CrtYd) (width 0.12)) 74 | (fp_line (start 10.5 -25.5) (end 10.5 25.5) (layer F.Fab) (width 0.12)) 75 | (fp_line (start -10.5 -24.2) (end -9.2 -25.5) (layer F.Fab) (width 0.12)) 76 | (fp_line (start -10.5 -25.5) (end 10.5 -25.5) (layer F.Fab) (width 0.12)) 77 | (fp_line (start -10.5 25.5) (end -10.5 -25.5) (layer F.Fab) (width 0.12)) 78 | (fp_line (start 10.5 25.5) (end -10.5 25.5) (layer F.Fab) (width 0.12)) 79 | (pad 1 thru_hole oval (at -8.89 -24.13) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 80 | (pad 2 thru_hole oval (at -8.89 -21.59) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 81 | (pad 3 thru_hole rect (at -8.89 -19.05) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 82 | (pad 4 thru_hole oval (at -8.89 -16.51) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 83 | (pad 5 thru_hole oval (at -8.89 -13.97) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 84 | (pad 6 thru_hole oval (at -8.89 -11.43) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 85 | (pad 7 thru_hole oval (at -8.89 -8.89) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 86 | (pad 8 thru_hole rect (at -8.89 -6.35) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 87 | (pad 9 thru_hole oval (at -8.89 -3.81) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 88 | (pad 10 thru_hole oval (at -8.89 -1.27) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 89 | (pad 11 thru_hole oval (at -8.89 1.27) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 90 | (pad 12 thru_hole oval (at -8.89 3.81) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 91 | (pad 13 thru_hole rect (at -8.89 6.35) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 92 | (pad 14 thru_hole oval (at -8.89 8.89) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 93 | (pad 15 thru_hole oval (at -8.89 11.43) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 94 | (pad 16 thru_hole oval (at -8.89 13.97) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 95 | (pad 17 thru_hole oval (at -8.89 16.51) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 96 | (pad 18 thru_hole rect (at -8.89 19.05) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 97 | (pad 19 thru_hole oval (at -8.89 21.59) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 98 | (pad 20 thru_hole oval (at -8.89 24.13) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 99 | (pad 21 thru_hole oval (at 8.89 24.13) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 100 | (pad 22 thru_hole oval (at 8.89 21.59) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 101 | (pad 23 thru_hole rect (at 8.89 19.05) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 102 | (pad 24 thru_hole oval (at 8.89 16.51) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 103 | (pad 25 thru_hole oval (at 8.89 13.97) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 104 | (pad 26 thru_hole oval (at 8.89 11.43) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 105 | (pad 27 thru_hole oval (at 8.89 8.89) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 106 | (pad 28 thru_hole rect (at 8.89 6.35) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 107 | (pad 29 thru_hole oval (at 8.89 3.81) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 108 | (pad 30 thru_hole oval (at 8.89 1.27) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 109 | (pad 31 thru_hole oval (at 8.89 -1.27) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 110 | (pad 32 thru_hole oval (at 8.89 -3.81) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 111 | (pad 33 thru_hole rect (at 8.89 -6.35) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 112 | (pad 34 thru_hole oval (at 8.89 -8.89) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 113 | (pad 35 thru_hole oval (at 8.89 -11.43) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 114 | (pad 36 thru_hole oval (at 8.89 -13.97) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 115 | (pad 37 thru_hole oval (at 8.89 -16.51) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 116 | (pad 38 thru_hole rect (at 8.89 -19.05) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 117 | (pad 39 thru_hole oval (at 8.89 -21.59) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 118 | (pad 40 thru_hole oval (at 8.89 -24.13) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 119 | (pad "" np_thru_hole oval (at 2.725 -24) (size 1.8 1.8) (drill 1.8) (layers *.Cu *.Mask)) 120 | (pad "" np_thru_hole oval (at -2.725 -24) (size 1.8 1.8) (drill 1.8) (layers *.Cu *.Mask)) 121 | (pad "" np_thru_hole oval (at -2.425 -20.97) (size 1.5 1.5) (drill 1.5) (layers *.Cu *.Mask)) 122 | (pad "" np_thru_hole oval (at 2.425 -20.97) (size 1.5 1.5) (drill 1.5) (layers *.Cu *.Mask)) 123 | (pad 41 thru_hole oval (at 0.5841 5.6) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 124 | (pad 42 thru_hole rect (at 3.1241 5.6) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 125 | (pad 43 thru_hole oval (at 5.6641 5.6) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask)) 126 | (pad 1 smd rect (at -8.89 -24.13) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 127 | (pad 2 smd rect (at -8.89 -21.59) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 128 | (pad 3 smd rect (at -8.89 -19.05) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 129 | (pad 4 smd rect (at -8.89 -16.51) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 130 | (pad 5 smd rect (at -8.89 -13.97) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 131 | (pad 6 smd rect (at -8.89 -11.43) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 132 | (pad 7 smd rect (at -8.89 -8.89) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 133 | (pad 8 smd rect (at -8.89 -6.35) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 134 | (pad 9 smd rect (at -8.89 -3.81) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 135 | (pad 10 smd rect (at -8.89 -1.27) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 136 | (pad 11 smd rect (at -8.89 1.27) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 137 | (pad 12 smd rect (at -8.89 3.81) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 138 | (pad 13 smd rect (at -8.89 6.35) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 139 | (pad 14 smd rect (at -8.89 8.89) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 140 | (pad 15 smd rect (at -8.89 11.43) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 141 | (pad 16 smd rect (at -8.89 13.97) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 142 | (pad 17 smd rect (at -8.89 16.51) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 143 | (pad 18 smd rect (at -8.89 19.05) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 144 | (pad 19 smd rect (at -8.89 21.59) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 145 | (pad 20 smd rect (at -8.89 24.13) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask)) 146 | (pad 21 smd rect (at 8.89 24.13) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 147 | (pad 22 smd rect (at 8.89 21.59) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 148 | (pad 23 smd rect (at 8.89 19.05) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 149 | (pad 24 smd rect (at 8.89 16.51) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 150 | (pad 25 smd rect (at 8.89 13.97) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 151 | (pad 26 smd rect (at 8.89 11.43) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 152 | (pad 27 smd rect (at 8.89 8.89) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 153 | (pad 28 smd rect (at 8.89 6.35) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 154 | (pad 29 smd rect (at 8.89 3.81) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 155 | (pad 30 smd rect (at 8.89 1.27) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 156 | (pad 31 smd rect (at 8.89 -1.27) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 157 | (pad 32 smd rect (at 8.89 -3.81) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 158 | (pad 33 smd rect (at 8.89 -6.35) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 159 | (pad 34 smd rect (at 8.89 -8.89) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 160 | (pad 35 smd rect (at 8.89 -11.43) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 161 | (pad 36 smd rect (at 8.89 -13.97) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 162 | (pad 37 smd rect (at 8.89 -16.51) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 163 | (pad 38 smd rect (at 8.89 -19.05) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 164 | (pad 39 smd rect (at 8.89 -21.59) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 165 | (pad 40 smd rect (at 8.89 -24.13) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask)) 166 | ) 167 | -------------------------------------------------------------------------------- /kicad/modules.pretty/SOIC-28W_7.5x17.9mm_Pitch1.27mm.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Housings_SOIC:SOIC-28W_7.5x17.9mm_Pitch1.27mm (layer F.Cu) (tedit 57503567) 2 | (descr "28-Lead Plastic Small Outline (SO) - Wide, 7.50 mm Body [SOIC] (see Microchip Packaging Specification 00000049BS.pdf)") 3 | (tags "SOIC 1.27") 4 | (attr smd) 5 | (fp_text reference U1 (at 0 -10.05) (layer F.SilkS) 6 | (effects (font (size 1 1) (thickness 0.15))) 7 | ) 8 | (fp_text value MAX3237CAI+ (at 0 10.05) (layer F.Fab) 9 | (effects (font (size 1 1) (thickness 0.15))) 10 | ) 11 | (fp_line (start -2.75 -8.95) (end 3.75 -8.95) (layer F.Fab) (width 0.15)) 12 | (fp_line (start 3.75 -8.95) (end 3.75 8.95) (layer F.Fab) (width 0.15)) 13 | (fp_line (start 3.75 8.95) (end -3.75 8.95) (layer F.Fab) (width 0.15)) 14 | (fp_line (start -3.75 8.95) (end -3.75 -7.95) (layer F.Fab) (width 0.15)) 15 | (fp_line (start -3.75 -7.95) (end -2.75 -8.95) (layer F.Fab) (width 0.15)) 16 | (fp_line (start -5.95 -9.3) (end -5.95 9.3) (layer F.CrtYd) (width 0.05)) 17 | (fp_line (start 5.95 -9.3) (end 5.95 9.3) (layer F.CrtYd) (width 0.05)) 18 | (fp_line (start -5.95 -9.3) (end 5.95 -9.3) (layer F.CrtYd) (width 0.05)) 19 | (fp_line (start -5.95 9.3) (end 5.95 9.3) (layer F.CrtYd) (width 0.05)) 20 | (fp_line (start -3.875 -9.125) (end -3.875 -8.875) (layer F.SilkS) (width 0.15)) 21 | (fp_line (start 3.875 -9.125) (end 3.875 -8.78) (layer F.SilkS) (width 0.15)) 22 | (fp_line (start 3.875 9.125) (end 3.875 8.78) (layer F.SilkS) (width 0.15)) 23 | (fp_line (start -3.875 9.125) (end -3.875 8.78) (layer F.SilkS) (width 0.15)) 24 | (fp_line (start -3.875 -9.125) (end 3.875 -9.125) (layer F.SilkS) (width 0.15)) 25 | (fp_line (start -3.875 9.125) (end 3.875 9.125) (layer F.SilkS) (width 0.15)) 26 | (fp_line (start -3.875 -8.875) (end -5.7 -8.875) (layer F.SilkS) (width 0.15)) 27 | (pad 1 smd rect (at -4.7 -8.255) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 28 | (pad 2 smd rect (at -4.7 -6.985) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 29 | (pad 3 smd rect (at -4.7 -5.715) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 30 | (pad 4 smd rect (at -4.7 -4.445) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 31 | (pad 5 smd rect (at -4.7 -3.175) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 32 | (pad 6 smd rect (at -4.7 -1.905) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 33 | (pad 7 smd rect (at -4.7 -0.635) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 34 | (pad 8 smd rect (at -4.7 0.635) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 35 | (pad 9 smd rect (at -4.7 1.905) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 36 | (pad 10 smd rect (at -4.7 3.175) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 37 | (pad 11 smd rect (at -4.7 4.445) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 38 | (pad 12 smd rect (at -4.7 5.715) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 39 | (pad 13 smd rect (at -4.7 6.985) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 40 | (pad 14 smd rect (at -4.7 8.255) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 41 | (pad 15 smd rect (at 4.7 8.255) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 42 | (pad 16 smd rect (at 4.7 6.985) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 43 | (pad 17 smd rect (at 4.7 5.715) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 44 | (pad 18 smd rect (at 4.7 4.445) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 45 | (pad 19 smd rect (at 4.7 3.175) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 46 | (pad 20 smd rect (at 4.7 1.905) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 47 | (pad 21 smd rect (at 4.7 0.635) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 48 | (pad 22 smd rect (at 4.7 -0.635) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 49 | (pad 23 smd rect (at 4.7 -1.905) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 50 | (pad 24 smd rect (at 4.7 -3.175) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 51 | (pad 25 smd rect (at 4.7 -4.445) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 52 | (pad 26 smd rect (at 4.7 -5.715) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 53 | (pad 27 smd rect (at 4.7 -6.985) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 54 | (pad 28 smd rect (at 4.7 -8.255) (size 2 0.6) (layers F.Cu F.Paste F.Mask)) 55 | (model Housings_SOIC.3dshapes/SOIC-28_7.5x17.9mm_Pitch1.27mm.wrl 56 | (at (xyz 0 0 0)) 57 | (scale (xyz 1 1 1)) 58 | (rotate (xyz 0 0 0)) 59 | ) 60 | ) 61 | -------------------------------------------------------------------------------- /kicad/modules.pretty/TO-92_Inline_Narrow_Oval.kicad_mod: -------------------------------------------------------------------------------- 1 | (module TO_SOT_Packages_THT:TO-92_Inline_Narrow_Oval (layer F.Cu) (tedit 633E1C3E) 2 | (descr "TO-92 leads in-line, narrow, oval pads, drill 0.6mm (see NXP sot054_po.pdf)") 3 | (tags "to-92 sc-43 sc-43a sot54 PA33 transistor") 4 | (fp_text reference U4 (at 4.826 -0.127 90) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value LM2950ACZ-3.3 (at 6.731 -0.254 90) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -1.4 1.95) (end -1.4 -2.65) (layer F.CrtYd) (width 0.05)) 11 | (fp_line (start -1.4 1.95) (end 3.95 1.95) (layer F.CrtYd) (width 0.05)) 12 | (fp_line (start -0.43 1.7) (end 2.97 1.7) (layer F.SilkS) (width 0.15)) 13 | (fp_arc (start 1.27 0) (end 1.27 -2.4) (angle -135) (layer F.SilkS) (width 0.15)) 14 | (fp_arc (start 1.27 0) (end 1.27 -2.4) (angle 135) (layer F.SilkS) (width 0.15)) 15 | (fp_line (start -1.4 -2.65) (end 3.95 -2.65) (layer F.CrtYd) (width 0.05)) 16 | (fp_line (start 3.95 1.95) (end 3.95 -2.65) (layer F.CrtYd) (width 0.05)) 17 | (pad 2 thru_hole oval (at 1.27 0 180) (size 0.89916 1.50114) (drill 0.6) (layers *.Cu *.Mask)) 18 | (pad 3 thru_hole oval (at 2.54 0 180) (size 0.89916 1.50114) (drill 0.6) (layers *.Cu *.Mask)) 19 | (pad 1 thru_hole oval (at 0 0 180) (size 0.89916 1.50114) (drill 0.6) (layers *.Cu *.Mask)) 20 | (model TO_SOT_Packages_THT.3dshapes/TO-92_Inline_Narrow_Oval.wrl 21 | (at (xyz 0.05 0 0)) 22 | (scale (xyz 1 1 1)) 23 | (rotate (xyz 0 0 -90)) 24 | ) 25 | ) 26 | -------------------------------------------------------------------------------- /kicad/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (lib (name Pico_Wifi_modem)(type Legacy)(uri ${KIPRJMOD}/library/Pico_Wifi_modem.lib)(options "")(descr "")) 3 | ) 4 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated Cmake Pico project file 2 | 3 | cmake_minimum_required(VERSION 3.13) 4 | 5 | set(CMAKE_C_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD 17) 7 | set(CMAKE_BUILD_TYPE Debug) 8 | set(PICO_BOARD pico_w) 9 | set(PICO_PLATFORM rp2040) 10 | set(PICO_COMPILER pico_arm_gcc) 11 | set(PROJECT_NAME wifi_modem) 12 | set(CYW43_HOST_NAME "PicoW2") 13 | 14 | # Pull in Raspberry Pi Pico SDK (must be before project) 15 | include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake) 16 | 17 | project(${PROJECT_NAME}) 18 | 19 | # Initialise the Raspberry Pi Pico SDK 20 | pico_sdk_init() 21 | 22 | add_executable(${PROJECT_NAME} 23 | ${PROJECT_NAME}.cpp 24 | ) 25 | target_compile_definitions(${PROJECT_NAME} PRIVATE 26 | CYW43_HOST_NAME=\"${CYW43_HOST_NAME}\" 27 | ) 28 | target_include_directories(${PROJECT_NAME} PRIVATE 29 | ${CMAKE_CURRENT_LIST_DIR} 30 | ) 31 | target_link_libraries(${PROJECT_NAME} 32 | pico_cyw43_arch_lwip_threadsafe_background 33 | pico_stdlib 34 | hardware_i2c 35 | ) 36 | 37 | pico_add_extra_outputs(${PROJECT_NAME}) 38 | 39 | # enable usb output, disable uart output 40 | pico_enable_stdio_usb(${PROJECT_NAME} 0) 41 | pico_enable_stdio_uart(${PROJECT_NAME} 1) 42 | -------------------------------------------------------------------------------- /src/at_basic.h: -------------------------------------------------------------------------------- 1 | // 2 | // ATA manually answer an incoming call 3 | // 4 | char *answerCall(char *atCmd) { 5 | tcpClient = serverGetClient(&tcpServer, &tcpClient0); 6 | gpio_put(RI, !ACTIVE); // we've picked up so ringing stops 7 | ringing = false; 8 | ringCount = 0; 9 | if( settings.telnet != NO_TELNET ) { 10 | // send incantation to switch from line mode to character mode 11 | bytesOut += tcpWriteBuf(tcpClient, toCharModeMagic, sizeof toCharModeMagic); 12 | } 13 | sendResult(R_RING_IP); 14 | sleep_ms(1000); 15 | connectTime = millis(); 16 | dtrWentInactive = false; 17 | sendResult(R_CONNECT); 18 | gpio_put(DCD, ACTIVE); // we've got a carrier signal 19 | amClient = false; 20 | state = ONLINE; 21 | uart_tx_wait_blocking(uart0); // drain the UART's Tx FIFO 22 | return atCmd; 23 | } 24 | 25 | // 26 | // ATC? query WiFi connection status 27 | // ATC0 disconnect from WiFi network 28 | // ATC1 connect to WiFi network 29 | // 30 | char *wifiConnection(char *atCmd) { 31 | switch( atCmd[0] ) { 32 | case '?': 33 | ++atCmd; 34 | printf("%c\r\n", cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP ? '1' : '0'); 35 | if( !atCmd[0] ) { 36 | sendResult(R_OK); 37 | } 38 | break; 39 | case '0': 40 | ++atCmd; 41 | case NUL: 42 | cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); 43 | if( !atCmd[0] ) { 44 | sendResult(R_OK); 45 | } 46 | gpio_put(DSR, !ACTIVE); // modem is not ready 47 | break; 48 | case '1': 49 | ++atCmd; 50 | if( settings.ssid[0] && settings.wifiPassword[0] ) { 51 | if( !settings.quiet && settings.extendedCodes ) { 52 | printf("CONNECTING TO SSID %s", settings.ssid); 53 | } 54 | cyw43_arch_wifi_connect_async(settings.ssid, settings.wifiPassword, CYW43_AUTH_WPA2_AES_PSK); 55 | for( int i = 0; i < 50; ++i ) { 56 | sleep_ms(500); 57 | if( !settings.quiet && settings.extendedCodes ) { 58 | uart_putc(uart0, '.'); 59 | } 60 | if( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP ) { 61 | break; 62 | } 63 | } 64 | if( !settings.quiet && settings.extendedCodes ) { 65 | crlf(); 66 | } 67 | if( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_UP ) { 68 | sendResult(R_ERROR); 69 | } else { 70 | gpio_put(DSR, ACTIVE); // modem is ready 71 | dns_init(); 72 | if( !settings.quiet && settings.extendedCodes ) { 73 | printf("CONNECTED TO %s IP ADDRESS: %s\r\n", 74 | settings.ssid, ip4addr_ntoa(netif_ip4_addr(&cyw43_state.netif[0]))); 75 | } 76 | if( !atCmd[0] ) { 77 | sendResult(R_OK); 78 | } 79 | } 80 | } else { 81 | if( !settings.quiet && settings.extendedCodes ) { 82 | printf("Configure SSID and password. Type AT? for help.\r\n"); 83 | } 84 | sendResult(R_ERROR); 85 | } 86 | break; 87 | default: 88 | sendResult(R_ERROR); 89 | break; 90 | } 91 | return atCmd; 92 | } 93 | 94 | // 95 | // ATDSn speed dial a number 96 | // 97 | char *dialNumber(char *atCmd); 98 | 99 | char *speedDialNumber(char *atCmd) { 100 | char number[MAX_SPEED_DIAL_LEN + 1]; 101 | char slot = atCmd[0]; 102 | 103 | if( isdigit(slot) && settings.speedDial[slot - '0'][0] ) { 104 | ++atCmd; 105 | strncpy(number, settings.speedDial[slot - '0'], MAX_SPEED_DIAL_LEN); 106 | number[MAX_SPEED_DIAL_LEN] = NUL; 107 | dialNumber(number); 108 | } else { 109 | sendResult(R_ERROR); 110 | } 111 | return atCmd; 112 | } 113 | 114 | // 115 | // ATDThost[:port] dial a number 116 | // 117 | char *dialNumber(char *atCmd) { 118 | char *host, *port, *ptr; 119 | char tempNumber[MAX_SPEED_DIAL_LEN + 1]; 120 | int portNum; 121 | ip_addr_t remoteAddr; 122 | 123 | getHostAndPort(atCmd, host, port, portNum); 124 | if( !port ) { 125 | // check for host names that are 7 identical digits long 126 | // and dial from the corresponding speed dial slot 127 | bool speedDial = true; 128 | if( strlen(host) == MAGIC_SPEED_LEN && isdigit(host[0]) ) { 129 | for( int i = 0; i < MAGIC_SPEED_LEN; ++i ) { 130 | if( host[0] != host[i] ) { 131 | speedDial = false; 132 | break; 133 | } 134 | } 135 | } else { 136 | speedDial = false; 137 | } 138 | if( speedDial && settings.speedDial[host[0] - '0'][0] ) { 139 | strncpy(tempNumber, settings.speedDial[host[0] - '0'], MAX_SPEED_DIAL_LEN); 140 | tempNumber[MAX_SPEED_DIAL_LEN] = NUL; 141 | getHostAndPort(tempNumber, host, port, portNum); 142 | } else { 143 | // now check all the speed dial aliases for a match 144 | for( int i = 0; i < SPEED_DIAL_SLOTS; ++i ) { 145 | if( !strcasecmp(host, settings.alias[i]) ) { 146 | strncpy(tempNumber, settings.speedDial[i], MAX_SPEED_DIAL_LEN); 147 | tempNumber[MAX_SPEED_DIAL_LEN] = NUL; 148 | getHostAndPort(tempNumber, host, port, portNum); 149 | break; 150 | } 151 | } 152 | } 153 | } 154 | 155 | sessionTelnetType = settings.telnet; 156 | switch( host[0] ) { 157 | case '-': 158 | ++host; 159 | sessionTelnetType = NO_TELNET; 160 | break; 161 | case '=': 162 | ++host; 163 | sessionTelnetType = REAL_TELNET; 164 | break; 165 | case '+': 166 | ++host; 167 | sessionTelnetType = FAKE_TELNET; 168 | break; 169 | } 170 | 171 | if( !settings.quiet && settings.extendedCodes ) { 172 | printf("DIALLING %s:%u\r\n", host, portNum); 173 | uart_tx_wait_blocking(uart0); 174 | } 175 | sleep_ms(2000); // delay for ZMP to be able to detect CONNECT 176 | if( !uart_is_readable(uart0) ) { 177 | tcpClient = tcpConnect( &tcpClient0, host, portNum); 178 | if( tcpClient ) { 179 | connectTime = millis(); 180 | dtrWentInactive = false; 181 | sendResult(R_CONNECT); 182 | gpio_put(DCD, ACTIVE); 183 | state = ONLINE; 184 | amClient = true; 185 | } else { 186 | sendResult(R_NO_CARRIER); 187 | gpio_put(DCD, !ACTIVE); 188 | } 189 | } else { 190 | sendResult(R_NO_CARRIER); 191 | gpio_put(DCD, !ACTIVE); 192 | } 193 | atCmd[0] = NUL; 194 | return atCmd; 195 | } 196 | 197 | // 198 | // ATE? query command mode echo status 199 | // ATE0 disable command mode local echo 200 | // ATE1 enable command mode local echo 201 | // 202 | char *doEcho(char *atCmd) { 203 | switch( atCmd[0] ) { 204 | case '?': 205 | ++atCmd; 206 | printf("%u\r\n", settings.echo); 207 | if( !atCmd[0] ) { 208 | sendResult(R_OK); 209 | } 210 | break; 211 | case '0': 212 | case '1': 213 | case NUL: 214 | settings.echo = atCmd[0] == '1'; 215 | if( atCmd[0] ) { 216 | ++atCmd; 217 | } 218 | if( !atCmd[0] ) { 219 | sendResult(R_OK); 220 | } 221 | break; 222 | default: 223 | sendResult(R_ERROR); 224 | break; 225 | } 226 | return atCmd; 227 | } 228 | 229 | // 230 | // ATGEThttp://host[/path]: fetch a web page 231 | // 232 | // NOTE: http only: no https support 233 | // 234 | char *httpGet(char *atCmd) { 235 | char *host, *path, *port; 236 | int portNum; 237 | port = strrchr(atCmd, ':'); 238 | host = strstr(atCmd, "http://"); 239 | if( !port || port == host + 4) { 240 | portNum = HTTP_PORT; 241 | } else { 242 | portNum = atoi(port + 1); 243 | *port = NUL; 244 | } 245 | if( !host ) { 246 | sendResult(R_ERROR); 247 | return atCmd; 248 | } else { 249 | host += 7; // skip over http:// 250 | path = strchr(host, '/'); 251 | } 252 | if( path ) { 253 | *path = NUL; 254 | ++path; 255 | } 256 | #if DEBUG 257 | printf("Getting path /"); 258 | if( path ) { 259 | printf("%s", path); 260 | } 261 | printf(" from port %u of host %s...\r\n", portNum, host); 262 | #endif 263 | // Establish connection 264 | tcpClient = tcpConnect(&tcpClient0, host, portNum); 265 | if( !tcpClient ) { 266 | sendResult(R_NO_CARRIER); 267 | gpio_put(DCD, !ACTIVE); 268 | } else { 269 | connectTime = millis(); 270 | dtrWentInactive = false; 271 | sendResult(R_CONNECT); 272 | gpio_put(DCD, ACTIVE); 273 | amClient = true; 274 | state = ONLINE; 275 | 276 | // Send a HTTP request before continuing the connection as usual 277 | bytesOut += tcpWriteStr(tcpClient, "GET /"); 278 | if( path ) { 279 | bytesOut += tcpWriteStr(tcpClient, path); 280 | } 281 | bytesOut += tcpWriteStr(tcpClient, " HTTP/1.1\r\nHost: "); 282 | bytesOut += tcpWriteStr(tcpClient, host); 283 | bytesOut += tcpWriteStr(tcpClient, "\r\nConnection: close\r\n\r\n"); 284 | } 285 | atCmd[0] = NUL; 286 | return atCmd; 287 | } 288 | 289 | // 290 | // ATH go offline (if connected to a host) 291 | // 292 | char *hangup(char *atCmd) { 293 | if( tcpIsConnected(tcpClient) ) { 294 | endCall(); 295 | } else { 296 | sendResult(R_OK); 297 | } 298 | return atCmd; 299 | } 300 | 301 | // 302 | // AT? help: paged output, uses dual columns if defined screen width 303 | // is at least 80 characters, single columns if less. 304 | // 305 | // There must be an even number of help strings defined. If you end up 306 | // with an odd number of strings, add an empty string ("") at the end 307 | // to pad things out. 308 | // 309 | const char helpStr01[] = "Help..........: AT?"; 310 | const char helpStr02[] = "Repeat command: A/"; 311 | const char helpStr03[] = "Answer call...: ATA"; 312 | const char helpStr04[] = "WiFi connect..: ATCn"; 313 | const char helpStr05[] = "Speed dial....: ATDSn"; 314 | const char helpStr06[] = "Dial host.....: ATDThost[:port]"; 315 | const char helpStr07[] = "Command echo..: ATEn"; 316 | const char helpStr08[] = "HTTP get......: ATGEThttp://host[/page]"; 317 | const char helpStr09[] = "Hang up.......: ATH"; 318 | const char helpStr10[] = "Network info..: ATI"; 319 | const char helpStr11[] = "Handle Telnet.: ATNETn"; 320 | const char helpStr12[] = "Leave cmd mode: ATO"; 321 | const char helpStr13[] = "Quiet mode....: ATQn"; 322 | const char helpStr14[] = "NIST date.time: ATRD/ATRT"; 323 | const char helpStr15[] = "Auto answer...: ATS0=n"; 324 | const char helpStr16[] = "Verbose mode..: ATVn"; 325 | const char helpStr17[] = "Extended codes: ATXn"; 326 | const char helpStr18[] = "Modem reset...: ATZ"; 327 | const char helpStr19[] = "DTR handling..: AT&D"; 328 | const char helpStr20[] = "Fact. defaults: AT&F"; 329 | const char helpStr21[] = "Flow control..: AT&Kn"; 330 | const char helpStr22[] = "Server passwd.: AT&R=server password"; 331 | const char helpStr23[] = "Show settings.: AT&Vn"; 332 | const char helpStr24[] = "Update NVRAM..: AT&W"; 333 | const char helpStr25[] = "Set speed dial: AT&Zn=host[:port],alias"; 334 | const char helpStr26[] = "Auto execute..: AT$AE=AT command"; 335 | const char helpStr27[] = "Are You There?: AT$AYT"; 336 | const char helpStr28[] = "Busy message..: AT$BM=busy message"; 337 | const char helpStr29[] = "mDNS name.....: AT$MDNS=mDNS name"; 338 | const char helpStr30[] = "WiFi password.: AT$PASS=WiFi password"; 339 | const char helpStr31[] = "Serial speed..: AT$SB=n"; 340 | const char helpStr32[] = "Server port...: AT$SP=n"; 341 | const char helpStr33[] = "WiFi SSID.....: AT$SSID=ssid"; 342 | const char helpStr34[] = "Data config...: AT$SU=dps"; 343 | const char helpStr35[] = "Location......: AT$TTL=telnet location"; 344 | const char helpStr36[] = "Terminal size.: AT$TTS=WxH"; 345 | const char helpStr37[] = "Terminal type.: AT$TTY=terminal type"; 346 | const char helpStr38[] = "Startup wait..: AT$W=n"; 347 | const char helpStr39[] = "Query most commands followed by '?'"; 348 | const char helpStr40[] = "e.g. ATQ?, AT&K?, AT$SSID?"; 349 | 350 | const char* const helpStrs[] = { 351 | helpStr01, helpStr02, helpStr03, helpStr04, helpStr05, helpStr06, 352 | helpStr07, helpStr08, helpStr09, helpStr10, helpStr11, helpStr12, 353 | helpStr13, helpStr14, helpStr15, helpStr16, helpStr17, helpStr18, 354 | helpStr19, helpStr20, helpStr21, helpStr22, helpStr23, helpStr24, 355 | helpStr25, helpStr26, helpStr27, helpStr28, helpStr29, helpStr30, 356 | helpStr31, helpStr32, helpStr33, helpStr34, helpStr35, helpStr36, 357 | helpStr37, helpStr38, helpStr39, helpStr40 358 | }; 359 | #define NUM_HELP_STRS (sizeof(helpStrs) / sizeof(helpStrs[0])) 360 | 361 | char *showHelp(char *atCmd) { 362 | char helpLine[80]; 363 | 364 | PagedOut("AT Command Summary:", true); 365 | if( settings.width >= 80 ) { 366 | // dual columns 367 | for( int i=0; ipcb->remote_ip)); 487 | if( PagedOut(infoLine) ) break; 488 | snprintf(infoLine, sizeof infoLine, "Call length: %s", connectTimeString()); 489 | if( PagedOut(infoLine) ) break; 490 | } else { 491 | if( PagedOut("Call status: NOT CONNECTED") ) break; 492 | } 493 | } while( false ); 494 | if( !atCmd[0] ) { 495 | sendResult(R_OK); 496 | } 497 | return atCmd; 498 | } 499 | 500 | // 501 | // ATNET? query Telnet handling status 502 | // ATNET0 turn off Telnet handling 503 | // ATNET1 turn on true Telnet handling 504 | // ATNET2 turn on BBS (fake) Telnet handling 505 | // 506 | char *doTelnetMode(char* atCmd) { 507 | switch( atCmd[0] ) { 508 | case '?': 509 | ++atCmd; 510 | printf("%u\r\n", settings.telnet); 511 | if( !atCmd[0] ) { 512 | sendResult(R_OK); 513 | } 514 | break; 515 | case NUL: 516 | case '0': // no Telnet processing 517 | case '1': // real Telnet (double IACs, add NUL after CR) 518 | case '2': // fake (BBS) Telnet (double IACs) 519 | if( atCmd[0] ) { 520 | settings.telnet = atCmd[0] - '0'; 521 | ++atCmd; 522 | } else { 523 | settings.telnet = NO_TELNET; 524 | } 525 | if( !atCmd[0] ) { 526 | sendResult(R_OK); 527 | } 528 | break; 529 | default: 530 | sendResult(R_ERROR); 531 | break; 532 | } 533 | return atCmd; 534 | } 535 | 536 | // 537 | // ATO go online (if connected to a host) 538 | // 539 | char *goOnline(char *atCmd) { 540 | if( tcpIsConnected(tcpClient) ) { 541 | state = ONLINE; 542 | dtrWentInactive = false; 543 | sendResult(R_CONNECT); 544 | } else { 545 | sendResult(R_ERROR); 546 | } 547 | return atCmd; 548 | } 549 | 550 | // 551 | // ATQ? query quiet mode status 552 | // ATQ0 disable quiet mode (results issued) 553 | // ATQ1 enable quiet mode (no results issued) 554 | // 555 | char *doQuiet(char *atCmd) { 556 | switch( atCmd[0] ) { 557 | case '?': 558 | ++atCmd; 559 | printf("%u\r\n", settings.quiet); 560 | if( !atCmd[0] ) { 561 | sendResult(R_OK); 562 | } 563 | break; 564 | case '0': 565 | case '1': 566 | case NUL: 567 | settings.quiet = atCmd[0] == '1'; 568 | if( atCmd[0] ) { 569 | ++atCmd; 570 | } 571 | if( !atCmd[0] ) { 572 | sendResult(R_OK); 573 | } 574 | break; 575 | default: 576 | sendResult(R_ERROR); 577 | break; 578 | } 579 | return atCmd; 580 | } 581 | 582 | // 583 | // ATRD Displays the UTC date and time from NIST in the format 584 | // ATRT "YY-MM-DD HH:MM:SS" 585 | // 586 | char *doDateTime(char *atCmd) { 587 | bool ok = false; 588 | uint16_t len; 589 | 590 | if( !tcpIsConnected(tcpClient) ) { 591 | char result[80], *ptr; 592 | tcpClient = tcpConnect(&tcpClient0, NIST_HOST, NIST_PORT); 593 | if( tcpClient ) { 594 | gpio_put(DCD, ACTIVE); 595 | // read date/time from NIST 596 | result[0] = tcpReadByte(tcpClient, 1000); 597 | if( result[0] == '\n' ) { // leading LF 598 | len = tcpReadBytesUntil(tcpClient, '\n', result, (sizeof result) - 1); 599 | if( len ) { // string read? 600 | result[len] = NUL; 601 | ptr = strtok(result, " "); 602 | if( ptr ) { // found Julian day? 603 | ptr = strtok(NULL, " "); 604 | if( ptr ) { // found date? 605 | printf("%s ", ptr); 606 | ptr = strtok(NULL, " "); 607 | if( ptr ) { // found time? 608 | printf("%s\r\n", ptr); 609 | ok = true; 610 | } 611 | } 612 | } 613 | } 614 | } 615 | tcpClientClose(tcpClient); 616 | gpio_put(DCD, !ACTIVE); 617 | } 618 | } 619 | if( ok ) { 620 | if( !atCmd[0] ) { 621 | sendResult(R_OK); 622 | } 623 | } else { 624 | sendResult(R_ERROR); 625 | } 626 | return atCmd; 627 | } 628 | 629 | // 630 | // ATS0? query auto answer configuration 631 | // ATS0=0 disable auto answer 632 | // ATS0=n enable auto answer after n rings 633 | // 634 | char *doAutoAnswerConfig(char *atCmd) { 635 | switch( atCmd[0] ) { 636 | case '?': 637 | ++atCmd; 638 | printf("%u\r\n", settings.autoAnswer); 639 | if( !atCmd[0] ) { 640 | sendResult(R_OK); 641 | } 642 | break; 643 | case '=': 644 | ++atCmd; 645 | if( isdigit(atCmd[0]) ) { 646 | settings.autoAnswer = atoi(atCmd); 647 | while( isdigit(atCmd[0]) ) { 648 | ++atCmd; 649 | } 650 | if( !atCmd[0] ) { 651 | sendResult(R_OK); 652 | } 653 | } else { 654 | sendResult(R_ERROR); 655 | } 656 | break; 657 | default: 658 | sendResult(R_ERROR); 659 | break; 660 | } 661 | return atCmd; 662 | } 663 | 664 | // 665 | // ATS2? query escape character 666 | // ATS2=[128..255] disable escape character 667 | // ATS2=[0..127] set and enable escape character 668 | // 669 | char *doEscapeCharConfig(char *atCmd) { 670 | switch( atCmd[0] ) { 671 | case '?': 672 | ++atCmd; 673 | printf("%u\r\n", settings.escChar); 674 | if( !atCmd[0] ) { 675 | sendResult(R_OK); 676 | } 677 | break; 678 | case '=': 679 | ++atCmd; 680 | if( isdigit(atCmd[0]) ) { 681 | settings.escChar = atoi(atCmd); 682 | while( isdigit(atCmd[0]) ) { 683 | ++atCmd; 684 | } 685 | if( !atCmd[0] ) { 686 | sendResult(R_OK); 687 | } 688 | } else { 689 | sendResult(R_ERROR); 690 | } 691 | break; 692 | default: 693 | sendResult(R_ERROR); 694 | break; 695 | } 696 | return atCmd; 697 | } 698 | 699 | // 700 | // ATV? query verbose mode status 701 | // ATV0 disable verbose mode (results are shown as numbers) 702 | // ATV1 enable verbose nmode (results are shown as text) 703 | // 704 | char *doVerbose(char* atCmd) { 705 | switch( atCmd[0] ) { 706 | case '?': 707 | ++atCmd; 708 | printf("%u\r\n", settings.verbose); 709 | if( !atCmd[0] ) { 710 | sendResult(R_OK); 711 | } 712 | break; 713 | case '0': 714 | case '1': 715 | case NUL: 716 | settings.verbose = atCmd[0] == '1'; 717 | if( atCmd[0] ) { 718 | ++atCmd; 719 | } 720 | if( !atCmd[0] ) { 721 | sendResult(R_OK); 722 | } 723 | break; 724 | default: 725 | sendResult(R_ERROR); 726 | break; 727 | } 728 | return atCmd; 729 | } 730 | 731 | // 732 | // ATX? query extended results 733 | // ATX0 disable extended results 734 | // ATX1 enable extended results 735 | // 736 | char *doExtended(char *atCmd) { 737 | switch( atCmd[0] ) { 738 | case '?': 739 | ++atCmd; 740 | printf("%u\r\n", settings.extendedCodes); 741 | if( !atCmd[0] ) { 742 | sendResult(R_OK); 743 | } 744 | break; 745 | case '0': 746 | case '1': 747 | case NUL: 748 | settings.extendedCodes = atCmd[0] == '1'; 749 | if( atCmd[0] ) { 750 | ++atCmd; 751 | } 752 | if( !atCmd[0] ) { 753 | sendResult(R_OK); 754 | } 755 | break; 756 | default: 757 | sendResult(R_ERROR); 758 | break; 759 | } 760 | return atCmd; 761 | } 762 | 763 | // 764 | // ATZ restart the sketch 765 | // 766 | char *resetToNvram(char *atCmd) { 767 | uart_tx_wait_blocking(uart0); // allow for CR/LF to finish 768 | watchdog_enable(1, false); 769 | while( true ) { 770 | tight_loop_contents(); 771 | } 772 | return atCmd; // should never actually get here... 773 | } 774 | 775 | -------------------------------------------------------------------------------- /src/at_extended.h: -------------------------------------------------------------------------------- 1 | // 2 | // AT&F reset NVRAM to defaults and load them into current settings 3 | // 4 | char *factoryDefaults(char *atCmd) { 5 | settings.magicNumber = MAGIC_NUMBER; 6 | settings.ssid[0] = NUL; 7 | settings.wifiPassword[0] = NUL; 8 | settings.serialSpeed = DEFAULT_SPEED; 9 | settings.dataBits = 8; 10 | settings.parity = UART_PARITY_NONE; 11 | settings.stopBits = 1; 12 | settings.rtsCts = false; 13 | settings.width = 80; 14 | settings.height = 24; 15 | settings.escChar = ESC_CHAR; 16 | for( int i=0; i < SPEED_DIAL_SLOTS; ++i ) { 17 | settings.alias[i][0] = NUL; 18 | settings.speedDial[i][0] = NUL; 19 | } 20 | strcpy(settings.mdnsName, "picomodem"); 21 | settings.autoAnswer = 0; 22 | settings.listenPort = 0; 23 | strcpy(settings.busyMsg, "Sorry, the system is currently busy. Please try again later."); 24 | settings.serverPassword[0] = NUL; 25 | settings.echo = true; 26 | settings.telnet = REAL_TELNET; 27 | settings.autoExecute[0] = NUL; 28 | strcpy(settings.terminal, "ansi"); 29 | strcpy(settings.location, "Computer Room"); 30 | settings.startupWait = false; 31 | settings.extendedCodes = true; 32 | settings.verbose = true; 33 | settings.quiet = false; 34 | settings.dtrHandling = DTR_IGNORE; 35 | 36 | strcpy(settings.alias[0], "particles"); 37 | strcpy(settings.speedDial[0], "+particlesbbs.dyndns.org:6400"); 38 | strcpy(settings.alias[1], "altair"); 39 | strcpy(settings.speedDial[1], "altair.virtualaltair.com:4667"); 40 | strcpy(settings.alias[2], "heatwave"); 41 | strcpy(settings.speedDial[2], "heatwave.ddns.net:9640"); 42 | 43 | bool ok = writeSettings(&settings); 44 | 45 | if( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP ) { 46 | cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); 47 | } 48 | 49 | if( atCmd ) { 50 | atCmd += 2; 51 | if( !atCmd[0] && ok) { 52 | sendResult(R_OK); 53 | } else if( !ok ) { 54 | sendResult(R_ERROR); 55 | } 56 | } 57 | return atCmd; 58 | } 59 | 60 | // 61 | // AT&D? DTR handling setting 62 | // AT&D0 ignore DTR 63 | // AT&D1 go offline when DTR transitions to off 64 | // AT&D2 hang up when DTR transitions to off 65 | // AT&D3 reset when DTR transitions to off 66 | // 67 | char *doDtrHandling(char *atCmd) { 68 | switch( atCmd[0] ) { 69 | case '?': 70 | ++atCmd; 71 | printf("%u\r\n", (uint8_t)settings.dtrHandling); 72 | if( !atCmd[0] ) { 73 | sendResult(R_OK); 74 | } 75 | break; 76 | case NUL: 77 | case '0': 78 | case '1': 79 | case '2': 80 | case '3': 81 | switch( atCmd[0] ) { 82 | case NUL: 83 | case '0': 84 | settings.dtrHandling = DTR_IGNORE; 85 | break; 86 | case '1': 87 | settings.dtrHandling = DTR_GOTO_COMMAND; 88 | break; 89 | case '2': 90 | settings.dtrHandling = DTR_END_CALL; 91 | break; 92 | case '3': 93 | settings.dtrHandling = DTR_RESET; 94 | break; 95 | } 96 | gpio_set_irq_enabled(DTR, GPIO_IRQ_EDGE_RISE, settings.dtrHandling != DTR_IGNORE); 97 | if( atCmd[0] ) { 98 | ++atCmd; 99 | } 100 | if( !atCmd[0] ) { 101 | sendResult(R_OK); 102 | } 103 | break; 104 | default: 105 | sendResult(R_ERROR); 106 | break; 107 | } 108 | return atCmd; 109 | } 110 | 111 | // 112 | // AT&K? query flow control setting 113 | // AT&K0 disable RTS/CTS flow control 114 | // AT&K1 enable RTS/CTS flow control 115 | // 116 | char *doFlowControl(char *atCmd) { 117 | switch( atCmd[0] ) { 118 | case '?': 119 | ++atCmd; 120 | printf("%u\r\n", settings.rtsCts); 121 | if( !atCmd[0] ) { 122 | sendResult(R_OK); 123 | } 124 | break; 125 | case '0': 126 | case '1': 127 | case NUL: 128 | settings.rtsCts = atCmd[0] == '1'; 129 | if( atCmd[0] ) { 130 | ++atCmd; 131 | } 132 | if( !atCmd[0] ) { 133 | sendResult(R_OK); 134 | } 135 | break; 136 | default: 137 | sendResult(R_ERROR); 138 | break; 139 | } 140 | return atCmd; 141 | } 142 | 143 | // 144 | // AT&R? query incoming password 145 | // AT&R=set incoming password 146 | // 147 | char *doServerPassword(char *atCmd) { 148 | switch( atCmd[0] ) { 149 | case '?': 150 | ++atCmd; 151 | printf("%s\r\n", settings.serverPassword); 152 | if( !atCmd[0] ) { 153 | sendResult(R_OK); 154 | } 155 | break; 156 | case '=': 157 | ++atCmd; 158 | strncpy(settings.serverPassword, atCmd, MAX_PWD_LEN); 159 | settings.serverPassword[MAX_PWD_LEN] = NUL; 160 | atCmd[0] = NUL; 161 | sendResult(R_OK); 162 | break; 163 | default: 164 | sendResult(R_ERROR); 165 | break; 166 | } 167 | return atCmd; 168 | } 169 | 170 | // 171 | // AT&V display current settings 172 | // AT&V0 display current settings 173 | // AT&V1 display NVRAM settings 174 | // 175 | char *displayAllSettings(char* atCmd) { 176 | switch( atCmd[0]) { 177 | case '0': 178 | ++atCmd; 179 | case NUL: 180 | displayCurrentSettings(); 181 | if( !atCmd[0] ) { 182 | sendResult(R_OK); 183 | } 184 | break; 185 | case '1': 186 | ++atCmd; 187 | displayStoredSettings(); 188 | if( !atCmd[0] ) { 189 | sendResult(R_OK); 190 | } 191 | break; 192 | default: 193 | sendResult(R_ERROR); 194 | break; 195 | } 196 | return atCmd; 197 | } 198 | 199 | // 200 | // AT&W: update NVRAM from current settings 201 | // 202 | char *updateNvram(char *atCmd) { 203 | writeSettings(&settings); 204 | if( !atCmd[0] ) { 205 | sendResult(R_OK); 206 | } 207 | return atCmd; 208 | } 209 | 210 | // 211 | // AT&Zn? show contents of speed dial slot n 212 | // AT&Zn=host,alias set speed dial slot n 213 | // 214 | char *doSpeedDialSlot(char *atCmd) { 215 | int slot; 216 | 217 | if( isdigit(atCmd[0]) ) { 218 | slot = atCmd[0] - '0'; 219 | ++atCmd; 220 | switch( atCmd[0] ) { 221 | case '?': 222 | ++atCmd; 223 | if( settings.speedDial[slot][0] ) { 224 | printf("%s,%s\r\n", 225 | settings.speedDial[slot], settings.alias[slot]); 226 | if( !atCmd[0] ) { 227 | sendResult(R_OK); 228 | } 229 | } else { 230 | sendResult(R_ERROR); 231 | } 232 | break; 233 | case '=': 234 | ++atCmd; 235 | if( !atCmd[0] ) { 236 | // erase slot 237 | settings.speedDial[slot][0] = NUL; 238 | settings.alias[slot][0] = NUL; 239 | sendResult(R_OK); 240 | } else { 241 | char *comma = strchr(atCmd, ','); 242 | if( !comma ) { 243 | sendResult(R_ERROR); 244 | } else { 245 | *comma++ = NUL; 246 | strncpy(settings.speedDial[slot], atCmd, MAX_SPEED_DIAL_LEN); 247 | settings.speedDial[slot][MAX_SPEED_DIAL_LEN] = NUL; 248 | strncpy(settings.alias[slot], comma, MAX_ALIAS_LEN); 249 | settings.alias[slot][MAX_ALIAS_LEN] = NUL; 250 | atCmd[0] = NUL; 251 | sendResult(R_OK); 252 | } 253 | } 254 | break; 255 | default: 256 | sendResult(R_ERROR); 257 | break; 258 | } 259 | } else { 260 | sendResult(R_ERROR); 261 | } 262 | return atCmd; 263 | } 264 | -------------------------------------------------------------------------------- /src/at_proprietary.h: -------------------------------------------------------------------------------- 1 | // 2 | // AT$AE? query auto execute command string 3 | // AT$AE=auto execute command string 4 | // 5 | char *doAutoExecute(char *atCmd) { 6 | switch( atCmd[0] ) { 7 | case '?': 8 | ++atCmd; 9 | printf("%s\r\n", settings.autoExecute); 10 | if( !atCmd[0] ) { 11 | sendResult(R_OK); 12 | } 13 | break; 14 | case '=': 15 | ++atCmd; 16 | strncpy(settings.autoExecute, atCmd, MAX_AUTOEXEC_LEN); 17 | settings.busyMsg[MAX_AUTOEXEC_LEN] = NUL; 18 | atCmd[0] = NUL; 19 | sendResult(R_OK); 20 | break; 21 | default: 22 | sendResult(R_ERROR); 23 | break; 24 | } 25 | return atCmd; 26 | } 27 | 28 | // 29 | // AT$AYT send "Are you there?" if in a Telnet session 30 | // 31 | char *doAreYouThere(char *atCmd) { 32 | 33 | static const uint8_t areYouThere[] = {IAC, AYT}; 34 | 35 | if( tcpIsConnected(tcpClient) && settings.telnet != NO_TELNET ) { 36 | state = ONLINE; 37 | dtrWentInactive = false; 38 | bytesOut += tcpWriteBuf(tcpClient, areYouThere, sizeof areYouThere); 39 | } else { 40 | sendResult(R_ERROR); 41 | } 42 | return atCmd; 43 | } 44 | 45 | // 46 | // AT$BM? query busy message 47 | // AT$BM=busy message set busy message 48 | // 49 | char *doBusyMessage(char *atCmd) { 50 | switch( atCmd[0] ) { 51 | case '?': 52 | ++atCmd; 53 | printf("%s\r\n", settings.busyMsg); 54 | if( !atCmd[0] ) { 55 | sendResult(R_OK); 56 | } 57 | break; 58 | case '=': 59 | ++atCmd; 60 | strncpy(settings.busyMsg, atCmd, MAX_BUSYMSG_LEN); 61 | settings.busyMsg[MAX_BUSYMSG_LEN] = NUL; 62 | atCmd[0] = NUL; 63 | sendResult(R_OK); 64 | break; 65 | default: 66 | sendResult(R_ERROR); 67 | break; 68 | } 69 | return atCmd; 70 | } 71 | 72 | // 73 | // AT$MDNS? query mDNS network name 74 | // AT$MDNS=mdnsname set mDNS network name 75 | // 76 | char *doMdnsName(char *atCmd) { 77 | switch( atCmd[0] ) { 78 | case '?': 79 | ++atCmd; 80 | printf("%s\r\n", settings.mdnsName); 81 | if( !atCmd[0] ) { 82 | sendResult(R_OK); 83 | } 84 | break; 85 | 86 | case '=': 87 | ++atCmd; 88 | strncpy(settings.mdnsName , atCmd, MAX_MDNSNAME_LEN); 89 | settings.mdnsName[MAX_MDNSNAME_LEN] = NUL; 90 | atCmd[0] = NUL; 91 | sendResult(R_OK); 92 | break; 93 | 94 | default: 95 | sendResult(R_ERROR); 96 | lastCmd[0] = NUL; 97 | break; 98 | } 99 | return atCmd; 100 | } 101 | 102 | // 103 | // AT$PASS? query WiFi password 104 | // AT$PASS=password set WiFi password 105 | // 106 | char *doWiFiPassword(char *atCmd) { 107 | switch( atCmd[0] ) { 108 | case '?': 109 | ++atCmd; 110 | printf("%s\r\n", settings.wifiPassword); 111 | if( !atCmd[0] ) { 112 | sendResult(R_OK); 113 | } 114 | break; 115 | case '=': 116 | ++atCmd; 117 | strncpy(settings.wifiPassword, atCmd, MAX_WIFI_PWD_LEN); 118 | settings.wifiPassword[MAX_WIFI_PWD_LEN] = NUL; 119 | atCmd[0] = NUL; 120 | sendResult(R_OK); 121 | break; 122 | default: 123 | sendResult(R_ERROR); 124 | break; 125 | } 126 | return atCmd; 127 | } 128 | 129 | // 130 | // AT$SB? query serial speed 131 | // AT$SB=n set serial speed 132 | // 133 | char *doSpeedChange(char *atCmd) { 134 | long newSerialSpeed; 135 | 136 | switch( atCmd[0] ) { 137 | case '?': 138 | ++atCmd; 139 | printf("%u\r\n", settings.serialSpeed); 140 | if( !atCmd[0] ) { 141 | sendResult(R_OK); 142 | } 143 | break; 144 | case '=': 145 | ++atCmd; 146 | newSerialSpeed = atol(atCmd); 147 | while( isdigit(*atCmd) ) { 148 | ++atCmd; 149 | } 150 | if( newSerialSpeed != settings.serialSpeed ) { 151 | switch( newSerialSpeed ) { 152 | case 110L: // 110 thru 76.8K are the 153 | case 300L: // standard 'BYE' rates, if 154 | case 450L: // you're wondering why 155 | case 600L: // unusual rates like 110, 450 156 | case 710L: // and 710 are in this list 157 | case 1200L: 158 | case 2400L: 159 | case 4800L: 160 | case 9600L: 161 | case 19200L: 162 | case 38400L: 163 | case 57600L: 164 | case 76800L: 165 | case 115200L: 166 | sendResult(R_OK); 167 | uart_tx_wait_blocking(uart0); // wait for transmit to finish 168 | uart_set_baudrate(uart0, newSerialSpeed); 169 | settings.serialSpeed = newSerialSpeed; 170 | break; 171 | 172 | default: 173 | sendResult(R_ERROR); 174 | break; 175 | } 176 | } else { 177 | sendResult(R_OK); 178 | } 179 | break; 180 | default: 181 | sendResult(R_ERROR); 182 | break; 183 | } 184 | return atCmd; 185 | } 186 | 187 | // 188 | // AT$SP? query inbound TCP port # 189 | // AT$SP=n set inbound TCP port # 190 | // NOTE: n=0 will disable the inbound TCP port 191 | // and a RING message will never be displayed 192 | // 193 | char *doServerPort(char *atCmd) { 194 | switch( atCmd[0] ) { 195 | case '?': 196 | ++atCmd; 197 | printf("%u\r\n", settings.listenPort); 198 | if( !atCmd[0] ) { 199 | sendResult(R_OK); 200 | } 201 | break; 202 | case '=': 203 | ++atCmd; 204 | settings.listenPort = atoi(atCmd); 205 | while( isdigit(atCmd[0]) ) { 206 | ++atCmd; 207 | } 208 | if( !atCmd[0] ) { 209 | sendResult(R_OK); 210 | } 211 | break; 212 | default: 213 | sendResult(R_ERROR); 214 | break; 215 | } 216 | return atCmd; 217 | } 218 | 219 | // 220 | // AT$SSID? query WiFi SSID 221 | // AT$SSID=ssid set WiFi SSID 222 | // 223 | char *doSSID(char *atCmd) { 224 | switch( atCmd[0] ) { 225 | case '?': 226 | ++atCmd; 227 | printf("%s\r\n", settings.ssid); 228 | if( !atCmd[0] ) { 229 | sendResult(R_OK); 230 | } 231 | break; 232 | case '=': 233 | ++atCmd; 234 | strncpy(settings.ssid, atCmd, MAX_SSID_LEN); 235 | settings.ssid[MAX_SSID_LEN] = NUL; 236 | atCmd[0] = NUL; 237 | sendResult(R_OK); 238 | break; 239 | default: 240 | sendResult(R_ERROR); 241 | break; 242 | } 243 | return atCmd; 244 | } 245 | 246 | // 247 | // AT$SU? query data configuration 248 | // AT$SU=nps set data configuration 249 | // n=7/8 data bits 250 | // p=N/E/O parity 251 | // s=1/2 stop bits 252 | // 253 | char *doDataConfig(char *atCmd) { 254 | bool ok = true; 255 | switch( atCmd[0] ) { 256 | case '?': 257 | ++atCmd; 258 | printf("%u", settings.dataBits); 259 | switch( settings.parity ) { 260 | case UART_PARITY_NONE: 261 | uart_putc(uart0, 'N'); 262 | break; 263 | case UART_PARITY_ODD: 264 | uart_putc(uart0, 'O'); 265 | break; 266 | case UART_PARITY_EVEN: 267 | uart_putc(uart0, 'E'); 268 | break; 269 | default: 270 | uart_putc(uart0, '?'); 271 | break; 272 | } 273 | printf("%u\r\n", settings.stopBits); 274 | if( !atCmd[0] ) { 275 | sendResult(R_OK); 276 | } 277 | break; 278 | case '=': 279 | switch( atCmd[1] ) { 280 | case '5': 281 | case '6': 282 | case '7': 283 | case '8': 284 | break; 285 | default: 286 | ok = false; 287 | break; 288 | } 289 | switch( toupper(atCmd[2]) ) { 290 | case 'N': 291 | case 'O': 292 | case 'E': 293 | break; 294 | default: 295 | ok = false; 296 | break; 297 | } 298 | switch( atCmd[3] ) { 299 | case '1': 300 | case '2': 301 | break; 302 | default: 303 | ok = false; 304 | break; 305 | } 306 | if( ok ) { 307 | settings.dataBits = atCmd[1] - '0'; 308 | switch( toupper(atCmd[2]) ) { 309 | case 'N': 310 | settings.parity = UART_PARITY_NONE; 311 | break; 312 | case 'O': 313 | settings.parity = UART_PARITY_ODD; 314 | break; 315 | case 'E': 316 | settings.parity = UART_PARITY_EVEN; 317 | break; 318 | } 319 | settings.stopBits = atCmd[3] - '0'; 320 | atCmd += 4; // skip over =dps 321 | if( !atCmd[0] ) { 322 | sendResult(R_OK); 323 | } 324 | } else { 325 | sendResult(R_ERROR); 326 | } 327 | break; 328 | default: 329 | sendResult(R_ERROR); 330 | break; 331 | } 332 | return atCmd; 333 | } 334 | 335 | // 336 | // AT$TTL? query Telnet location 337 | // AT$TTL=location set Telnet location 338 | // 339 | char *doLocation(char *atCmd) { 340 | switch( atCmd[0] ) { 341 | case '?': 342 | ++atCmd; 343 | printf("%s\r\n", settings.location); 344 | if( !atCmd[0] ) { 345 | sendResult(R_OK); 346 | } 347 | break; 348 | case '=': 349 | ++atCmd; 350 | strncpy(settings.location, atCmd, MAX_LOCATION_LEN); 351 | settings.location[MAX_LOCATION_LEN] = NUL; 352 | atCmd[0] = NUL; 353 | sendResult(R_OK); 354 | break; 355 | default: 356 | sendResult(R_ERROR); 357 | break; 358 | } 359 | return atCmd; 360 | } 361 | 362 | // 363 | // AT$TTS? query Telnet window size 364 | // AT$TTS=WxH set Telnet window size (width x height) 365 | // 366 | char *doWindowSize(char *atCmd) { 367 | switch( atCmd[0] ) { 368 | case '?': 369 | ++atCmd; 370 | printf("%ux%u\r\n", settings.width, settings.height); 371 | if( !atCmd[0] ) { 372 | sendResult(R_OK); 373 | } 374 | break; 375 | case '=': 376 | { 377 | char *width = atCmd + 1; 378 | char *height = strpbrk(width, "xX"); 379 | if( !width || !height ) { 380 | sendResult(R_ERROR); 381 | } else { 382 | ++height; // point to 1st char past X 383 | settings.width = atoi(width); 384 | settings.height = atoi(height); 385 | atCmd = height; 386 | while( isdigit(atCmd[0]) ) { 387 | ++atCmd; 388 | } 389 | if( !atCmd[0] ) { 390 | sendResult(R_OK); 391 | } 392 | } 393 | } 394 | break; 395 | default: 396 | sendResult(R_ERROR); 397 | break; 398 | } 399 | return atCmd; 400 | } 401 | 402 | // 403 | // AT$TTY? query Telnet terminal type 404 | // AT$TTY=terminal set Telnet terminal type 405 | // 406 | char *doTerminalType(char *atCmd) { 407 | switch( atCmd[0] ) { 408 | case '?': 409 | ++atCmd; 410 | printf("%s\r\n", settings.terminal); 411 | if( !atCmd[0] ) { 412 | sendResult(R_OK); 413 | } 414 | break; 415 | case '=': 416 | ++atCmd; 417 | strncpy(settings.terminal, atCmd, MAX_TERMINAL_LEN); 418 | settings.location[MAX_TERMINAL_LEN] = NUL; 419 | atCmd[0] = NUL; 420 | sendResult(R_OK); 421 | break; 422 | default: 423 | sendResult(R_ERROR); 424 | break; 425 | } 426 | return atCmd; 427 | } 428 | 429 | // 430 | // AT$W? query startup wait status 431 | // AT$W=0 disable startup wait 432 | // AT$W=1 enable startup wait (wait for a CR on startup) 433 | // 434 | char *doStartupWait(char *atCmd) { 435 | switch( atCmd[0] ) { 436 | case '?': 437 | ++atCmd; 438 | printf("%u\r\n", settings.startupWait); 439 | if( !atCmd[0] ) { 440 | sendResult(R_OK); 441 | } 442 | break; 443 | case '=': 444 | ++atCmd; 445 | switch( atCmd[0] ) { 446 | case '0': 447 | case '1': 448 | settings.startupWait = atCmd[0] == '1'; 449 | atCmd[0] = NUL; 450 | sendResult(R_OK); 451 | break; 452 | default: 453 | sendResult(R_ERROR); 454 | break; 455 | } 456 | break; 457 | default: 458 | sendResult(R_ERROR); 459 | break; 460 | } 461 | return atCmd; 462 | } 463 | -------------------------------------------------------------------------------- /src/build/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /src/eeprom.h: -------------------------------------------------------------------------------- 1 | // 2 | // External EEPROM routines 3 | // 4 | // I2C_xxx constants defined in wifi_modem.h 5 | // 6 | void initEEPROM(void) { 7 | i2c_init(i2c0, I2C_BAUD); 8 | gpio_set_function(I2C_SCL, GPIO_FUNC_I2C); 9 | gpio_set_function(I2C_SDA, GPIO_FUNC_I2C); 10 | } 11 | 12 | bool readSettings(SETTINGS_T *p) { 13 | const uint8_t addr[2] = {0,0}; 14 | int err; 15 | bool ok = false; 16 | 17 | if( i2c_write_blocking(i2c0, I2C_ADDR, addr, 2, true) == 2 ) { 18 | ok = i2c_read_blocking(i2c0, I2C_ADDR, (uint8_t *)p, sizeof(SETTINGS_T), false) == sizeof(SETTINGS_T); 19 | } 20 | return ok; 21 | } 22 | 23 | bool writeSettings(SETTINGS_T *p) { 24 | uint8_t data[3]; 25 | struct Settings current; 26 | bool ok = true; 27 | 28 | readSettings(¤t); 29 | 30 | for( int i=0; i> 8; 34 | data[1] = i & 0xFF; 35 | data[2] = ((uint8_t *)p)[i]; 36 | ok = i2c_write_blocking(i2c0, I2C_ADDR, data, 3, false) == 3; 37 | sleep_ms(5); 38 | } 39 | } 40 | return ok; 41 | } 42 | -------------------------------------------------------------------------------- /src/globals.h: -------------------------------------------------------------------------------- 1 | #ifndef _GLOBALS_H 2 | #define _GLOBALS_H 3 | 4 | // globals 5 | const char okStr[] = {"OK"}; 6 | const char connectStr[] = {"CONNECT"}; 7 | const char ringStr[] = {"RING"}; 8 | const char noCarrierStr[] = {"NO CARRIER"}; 9 | const char errorStr[] = {"ERROR"}; 10 | const char noAnswerStr[] = {"NO ANSWER"}; 11 | enum ResultCodes { R_OK, R_CONNECT, R_RING, R_NO_CARRIER, R_ERROR, R_NO_ANSWER, R_RING_IP }; 12 | const char * const resultCodes[] = { okStr, connectStr, ringStr, noCarrierStr, errorStr, noAnswerStr, ringStr}; 13 | enum DtrStates { DTR_IGNORE, DTR_GOTO_COMMAND, DTR_END_CALL, DTR_RESET}; 14 | 15 | typedef struct Settings { 16 | uint16_t magicNumber; 17 | char ssid[MAX_SSID_LEN + 1]; 18 | char wifiPassword[MAX_WIFI_PWD_LEN + 1]; 19 | uint32_t serialSpeed; 20 | uint8_t dataBits; 21 | uart_parity_t parity; 22 | uint8_t stopBits; 23 | bool rtsCts; 24 | uint8_t width, height; 25 | char escChar; 26 | char alias[SPEED_DIAL_SLOTS][MAX_ALIAS_LEN + 1]; 27 | char speedDial[SPEED_DIAL_SLOTS][MAX_SPEED_DIAL_LEN + 1]; 28 | char mdnsName[MAX_MDNSNAME_LEN + 1]; 29 | uint8_t autoAnswer; 30 | uint16_t listenPort; 31 | char busyMsg[MAX_BUSYMSG_LEN + 1]; 32 | char serverPassword[MAX_PWD_LEN + 1]; 33 | bool echo; 34 | uint8_t telnet; 35 | char autoExecute[MAX_AUTOEXEC_LEN + 1]; 36 | char terminal[MAX_TERMINAL_LEN + 1]; 37 | char location[MAX_LOCATION_LEN + 1]; 38 | bool startupWait; 39 | bool extendedCodes; 40 | bool verbose; 41 | bool quiet; 42 | DtrStates dtrHandling; 43 | } SETTINGS_T; 44 | 45 | typedef struct TCP_CLIENT_T_ { 46 | struct tcp_pcb *pcb; 47 | ip_addr_t remoteAddr; 48 | volatile bool connected; 49 | volatile bool connectFinished; 50 | volatile bool waitingForAck; 51 | volatile uint8_t rxBuff[TCP_CLIENT_RX_BUF_SIZE]; 52 | volatile uint16_t rxBuffLen; 53 | volatile uint16_t rxBuffHead; 54 | volatile uint16_t rxBuffTail; 55 | volatile uint16_t totLen; 56 | volatile uint8_t txBuff[TCP_CLIENT_TX_BUF_SIZE]; 57 | volatile uint16_t txBuffLen; 58 | volatile uint16_t txBuffHead; 59 | volatile uint16_t txBuffTail; 60 | } TCP_CLIENT_T; 61 | 62 | typedef struct TCP_SERVER_T_ { 63 | struct tcp_pcb *pcb; 64 | struct tcp_pcb *clientPcb; 65 | } TCP_SERVER_T; 66 | 67 | SETTINGS_T settings; 68 | TCP_CLIENT_T *tcpClient,tcpClient0,tcpDroppedClient; 69 | TCP_SERVER_T tcpServer; 70 | // incantation to switch from line mode to character mode 71 | const uint8_t toCharModeMagic[] = {IAC,WILL,SUP_GA,IAC,WILL,ECHO,IAC,WONT,LINEMODE}; 72 | uint32_t bytesIn = 0, bytesOut = 0; 73 | unsigned long connectTime = 0; 74 | char atCmd[MAX_CMD_LEN + 1], lastCmd[MAX_CMD_LEN + 1]; 75 | unsigned atCmdLen = 0; 76 | enum {CMD_NOT_IN_CALL, CMD_IN_CALL, ONLINE, PASSWORD} state = CMD_NOT_IN_CALL; 77 | bool ringing = false; // no incoming call 78 | uint8_t ringCount = 0; // current incoming call ring count 79 | uint32_t nextRingMs = 0; // time of mext RING result 80 | uint8_t escCount = 0; // Go to AT mode at "+++" sequence, that has to be counted 81 | uint32_t guardTime = 0; // When did we last receive a "+++" sequence 82 | char password[MAX_PWD_LEN + 1]; 83 | uint8_t passwordTries = 0; // # of unsuccessful tries at incoming password 84 | uint8_t passwordLen = 0; 85 | uint8_t txBuf[TX_BUF_SIZE]; // Transmit Buffer 86 | uint8_t sessionTelnetType; 87 | volatile bool dtrWentInactive = false; 88 | bool amClient = false; // true if we've connected TO a remote server 89 | #ifndef NDEBUG 90 | volatile uint16_t maxTotLen = 0; 91 | volatile uint16_t maxRxBuffLen = 0; 92 | uint16_t maxTxBuffLen = 0; 93 | err_t lastTcpWriteErr = ERR_OK; 94 | #endif 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /src/lwipopts.h: -------------------------------------------------------------------------------- 1 | #ifndef _LWIPOPTS_EXAMPLE_COMMONH_H 2 | #define _LWIPOPTS_EXAMPLE_COMMONH_H 3 | 4 | 5 | // Common settings used in most of the pico_w examples 6 | // (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) 7 | 8 | // allow override in some examples 9 | #ifndef NO_SYS 10 | #define NO_SYS 1 11 | #endif 12 | // allow override in some examples 13 | #ifndef LWIP_SOCKET 14 | #define LWIP_SOCKET 0 15 | #endif 16 | #if PICO_CYW43_ARCH_POLL 17 | #define MEM_LIBC_MALLOC 1 18 | #else 19 | // MEM_LIBC_MALLOC is incompatible with non polling versions 20 | #define MEM_LIBC_MALLOC 0 21 | #endif 22 | #define MEM_ALIGNMENT 4 23 | #define MEM_SIZE 4000 24 | #define MEMP_NUM_TCP_SEG 32 25 | #define MEMP_NUM_ARP_QUEUE 10 26 | #define PBUF_POOL_SIZE 24 27 | #define LWIP_ARP 1 28 | #define LWIP_ETHERNET 1 29 | #define LWIP_ICMP 1 30 | #define LWIP_RAW 1 31 | #define TCP_WND (8 * TCP_MSS) 32 | #define TCP_MSS 1460 33 | #define TCP_SND_BUF (8 * TCP_MSS) 34 | #define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) 35 | #define LWIP_NETIF_STATUS_CALLBACK 1 36 | #define LWIP_NETIF_LINK_CALLBACK 1 37 | #define LWIP_NETIF_HOSTNAME 1 38 | #define LWIP_NETCONN 0 39 | #define MEM_STATS 0 40 | #define SYS_STATS 0 41 | #define MEMP_STATS 0 42 | #define LINK_STATS 0 43 | // #define ETH_PAD_SIZE 2 44 | #define LWIP_CHKSUM_ALGORITHM 3 45 | #define LWIP_DHCP 1 46 | #define LWIP_IPV4 1 47 | #define LWIP_TCP 1 48 | #define LWIP_UDP 1 49 | #define LWIP_DNS 1 50 | #define LWIP_TCP_KEEPALIVE 1 51 | #define LWIP_NETIF_TX_SINGLE_PBUF 1 52 | #define DHCP_DOES_ARP_CHECK 0 53 | #define LWIP_DHCP_DOES_ACD_CHECK 0 54 | 55 | #ifndef NDEBUG 56 | #define LWIP_DEBUG 1 57 | #define LWIP_STATS 1 58 | #define LWIP_STATS_DISPLAY 1 59 | #endif 60 | 61 | #define ETHARP_DEBUG LWIP_DBG_OFF 62 | #define NETIF_DEBUG LWIP_DBG_OFF 63 | #define PBUF_DEBUG LWIP_DBG_OFF 64 | #define API_LIB_DEBUG LWIP_DBG_OFF 65 | #define API_MSG_DEBUG LWIP_DBG_OFF 66 | #define SOCKETS_DEBUG LWIP_DBG_OFF 67 | #define ICMP_DEBUG LWIP_DBG_OFF 68 | #define INET_DEBUG LWIP_DBG_OFF 69 | #define IP_DEBUG LWIP_DBG_OFF 70 | #define IP_REASS_DEBUG LWIP_DBG_OFF 71 | #define RAW_DEBUG LWIP_DBG_OFF 72 | #define MEM_DEBUG LWIP_DBG_OFF 73 | #define MEMP_DEBUG LWIP_DBG_OFF 74 | #define SYS_DEBUG LWIP_DBG_OFF 75 | #define TCP_DEBUG LWIP_DBG_OFF 76 | #define TCP_INPUT_DEBUG LWIP_DBG_OFF 77 | #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF 78 | #define TCP_RTO_DEBUG LWIP_DBG_OFF 79 | #define TCP_CWND_DEBUG LWIP_DBG_OFF 80 | #define TCP_WND_DEBUG LWIP_DBG_OFF 81 | #define TCP_FR_DEBUG LWIP_DBG_OFF 82 | #define TCP_QLEN_DEBUG LWIP_DBG_OFF 83 | #define TCP_RST_DEBUG LWIP_DBG_OFF 84 | #define UDP_DEBUG LWIP_DBG_OFF 85 | #define TCPIP_DEBUG LWIP_DBG_OFF 86 | #define PPP_DEBUG LWIP_DBG_OFF 87 | #define SLIP_DEBUG LWIP_DBG_OFF 88 | #define DHCP_DEBUG LWIP_DBG_OFF 89 | 90 | #endif /* __LWIPOPTS_H__ */ 91 | -------------------------------------------------------------------------------- /src/tcp_support.h: -------------------------------------------------------------------------------- 1 | // 2 | // lwIP interface functions 3 | // 4 | static volatile bool dnsLookupFinished = false; 5 | 6 | static void dnsLookupDone(const char *name, const ip_addr_t *ipaddr, void *arg) { 7 | ip_addr_t *resolved = (ip_addr_t *)arg; 8 | if( ipaddr && ipaddr->addr) { 9 | resolved->addr = ipaddr->addr; 10 | } 11 | dnsLookupFinished = true; 12 | } 13 | 14 | bool dnsLookup(const char *name, ip_addr_t *resolved) { 15 | 16 | dnsLookupFinished = false; 17 | ip4_addr_set_any(resolved); 18 | 19 | switch( dns_gethostbyname(name, resolved, dnsLookupDone, resolved) ) { 20 | case ERR_OK: 21 | return true; 22 | break; 23 | case ERR_INPROGRESS: 24 | break; 25 | default: 26 | return false; 27 | } 28 | while( !dnsLookupFinished ) { 29 | tight_loop_contents(); 30 | } 31 | return !ip4_addr_isany(resolved); 32 | } 33 | 34 | uint32_t millis(void) { 35 | return to_ms_since_boot(get_absolute_time()); 36 | } 37 | 38 | bool tcpIsConnected(TCP_CLIENT_T *client) { 39 | if( client && client->pcb && client->pcb->callback_arg ) { 40 | return client->connected; 41 | } 42 | return false; 43 | } 44 | 45 | err_t tcpClientClose(TCP_CLIENT_T *client) { 46 | err_t err = ERR_OK; 47 | 48 | cyw43_arch_lwip_begin(); 49 | if( client ) { 50 | client->connected = false; 51 | if( client->pcb ) { 52 | tcp_err( client->pcb, NULL); 53 | tcp_sent(client->pcb, NULL); 54 | tcp_poll(client->pcb, NULL, 0); 55 | tcp_recv(client->pcb, NULL); 56 | tcp_arg( client->pcb, NULL); 57 | err = tcp_close(client->pcb); 58 | if( err != ERR_OK ) { 59 | tcp_abort(client->pcb); 60 | err = ERR_ABRT; 61 | } 62 | client->pcb = NULL; 63 | } 64 | } 65 | cyw43_arch_lwip_end(); 66 | return err; 67 | } 68 | 69 | // NB: the PCB may have already been freed when this function is called 70 | static void tcpClientErr(void *arg, err_t err) { 71 | TCP_CLIENT_T *client = (TCP_CLIENT_T *)arg; 72 | 73 | if( client ) { 74 | client->connectFinished = true; 75 | client->connected = false; 76 | client->pcb = NULL; 77 | } 78 | } 79 | 80 | static err_t tcpSend(TCP_CLIENT_T *client) { 81 | err_t err = ERR_OK; 82 | uint32_t ints; 83 | 84 | if( client->txBuffLen ) { 85 | uint16_t maxLen = tcp_sndbuf(client->pcb); 86 | if( maxLen > 0 && tcp_sndqueuelen(client->pcb) < TCP_SND_QUEUELEN ) { 87 | if( client->txBuffLen < maxLen ) { 88 | maxLen = client->txBuffLen; 89 | } 90 | uint8_t tmp[maxLen]; 91 | // make copies of the head and length and work 92 | // with those in case tcp_write fails and we 93 | // have to re-send the same data later 94 | uint16_t tmpTxBuffHead = client->txBuffHead; 95 | uint16_t tmpTxBuffLen = client->txBuffLen; 96 | for( int i = 0; i < maxLen; ++i ) { 97 | tmp[i] = client->txBuff[tmpTxBuffHead++]; 98 | if( tmpTxBuffHead == TCP_CLIENT_TX_BUF_SIZE ) { 99 | tmpTxBuffHead = 0; 100 | } 101 | --tmpTxBuffLen; 102 | } 103 | err = tcp_write(client->pcb, tmp, maxLen, TCP_WRITE_FLAG_COPY); 104 | client->waitingForAck = err == ERR_OK; 105 | tcp_output(client->pcb); 106 | if( err == ERR_OK ) { 107 | client->txBuffHead = tmpTxBuffHead; 108 | ints = save_and_disable_interrupts(); 109 | client->txBuffLen = tmpTxBuffLen; 110 | restore_interrupts(ints); 111 | #ifndef NDEBUG 112 | } else { 113 | lastTcpWriteErr = err; 114 | #endif 115 | } 116 | } 117 | } 118 | return err; 119 | } 120 | 121 | static err_t tcpSent(void *arg, struct tcp_pcb *tpcb, u16_t len) { 122 | TCP_CLIENT_T *client = (TCP_CLIENT_T *)arg; 123 | err_t err = ERR_OK; 124 | 125 | if( client->txBuffLen ) { 126 | err = tcpSend(client); 127 | } else { 128 | client->waitingForAck = false; 129 | } 130 | return err; 131 | } 132 | 133 | // in the event that the tcp_write call in tcpSend failed earlier, 134 | // and there weren't any other packets waiting to be ACKed, try 135 | // sending any data in the txBuff again. 136 | static err_t tcpPoll(void *arg, struct tcp_pcb *tpcb) { 137 | TCP_CLIENT_T *client = (TCP_CLIENT_T *)arg; 138 | err_t err = ERR_OK; 139 | #ifndef NDEBUG 140 | static bool pollState = false; 141 | 142 | gpio_put(POLL_STATE_LED, pollState); 143 | pollState = !pollState; 144 | #endif 145 | if( !client->waitingForAck && client->txBuffLen ) { 146 | err = tcpSend(client); 147 | } 148 | return err; 149 | } 150 | 151 | static err_t tcpRecv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { 152 | TCP_CLIENT_T *client = (TCP_CLIENT_T *)arg; 153 | 154 | if( !p ) { 155 | return tcpClientClose(client); 156 | } 157 | if( p->tot_len > 0 && client ) { 158 | for( struct pbuf *q = p; q; q = q->next ) { 159 | for( int i = 0; i < q->len; ++i ) { 160 | client->rxBuff[client->rxBuffTail++] = ((uint8_t *)q->payload)[i]; 161 | if( client->rxBuffTail == TCP_CLIENT_RX_BUF_SIZE ) { 162 | client->rxBuffTail = 0; 163 | } 164 | ++client->rxBuffLen; 165 | } 166 | } 167 | #ifndef NDEBUG 168 | if( client->rxBuffLen > TCP_CLIENT_RX_BUF_SIZE ) { 169 | gpio_put(RXBUFF_OVFL, HIGH); 170 | } 171 | if( client->rxBuffLen > maxRxBuffLen ) { 172 | maxRxBuffLen = client->rxBuffLen; 173 | } 174 | #endif 175 | if( client->rxBuffLen <= TCP_MSS ) { 176 | tcp_recved(client->pcb, p->tot_len); 177 | } else { 178 | client->totLen += p->tot_len; 179 | #ifndef NDEBUG 180 | if( client->totLen > maxTotLen ) { 181 | maxTotLen = client->totLen; 182 | } 183 | #endif 184 | } 185 | } 186 | pbuf_free(p); 187 | return ERR_OK; 188 | } 189 | 190 | static err_t tcpHasConnected(void *arg, struct tcp_pcb *tpcb, err_t err) { 191 | TCP_CLIENT_T *client = (TCP_CLIENT_T*)arg; 192 | 193 | client->connectFinished = true; 194 | client->connected = err == ERR_OK; 195 | if( err != ERR_OK ) { 196 | tcpClientClose(client); 197 | } 198 | return ERR_OK; 199 | } 200 | 201 | TCP_CLIENT_T *tcpConnect(TCP_CLIENT_T *client, const char *host, int portNum) { 202 | if( !dnsLookup(host, &client->remoteAddr) ) { 203 | return NULL; 204 | } else { 205 | client->pcb = tcp_new_ip_type(IP_GET_TYPE(client->remoteAddr)); 206 | if( !client->pcb ) { 207 | return NULL; 208 | } 209 | } 210 | tcp_arg( client->pcb, client); 211 | tcp_recv(client->pcb, tcpRecv); 212 | tcp_sent(client->pcb, tcpSent); 213 | tcp_poll(client->pcb, tcpPoll, 2); 214 | tcp_err( client->pcb, tcpClientErr); 215 | tcp_nagle_disable(client->pcb); // disable Nalge algorithm by default 216 | 217 | client->rxBuffLen = 0; 218 | client->rxBuffHead = 0; 219 | client->rxBuffTail = 0; 220 | client->totLen = 0; 221 | 222 | client->txBuffLen = 0; 223 | client->txBuffHead = 0; 224 | client->txBuffTail = 0; 225 | 226 | client->connected = false; 227 | client->connectFinished = false; 228 | client->waitingForAck = false; 229 | 230 | cyw43_arch_lwip_begin(); 231 | err_t err = tcp_connect(client->pcb, &client->remoteAddr, portNum, tcpHasConnected); 232 | cyw43_arch_lwip_end(); 233 | 234 | if( err != ERR_OK ) { 235 | client->pcb = NULL; 236 | return NULL; 237 | } 238 | 239 | while( client->pcb && client->pcb->callback_arg && !client->connectFinished && !uart_is_readable(uart0)) { 240 | tight_loop_contents(); 241 | } 242 | if( !client->connected ) { 243 | client->pcb = NULL; 244 | return NULL; 245 | } 246 | return client; 247 | } 248 | 249 | // NB: the PCB may have already been freed when this function is called 250 | static void tcpServerErr(void *arg, err_t err) { 251 | TCP_SERVER_T *server = (TCP_SERVER_T *)arg; 252 | 253 | if( server ) { 254 | server->pcb = NULL; 255 | server->clientPcb = NULL; 256 | } 257 | } 258 | 259 | static err_t tcpServerAccept(void *arg, struct tcp_pcb *clientPcb, err_t err) { 260 | TCP_SERVER_T *server = (TCP_SERVER_T*)arg; 261 | 262 | if( err != ERR_OK || !clientPcb ) { 263 | //### printf("Failure in accept: %d\n",err); //### 264 | server->clientPcb = NULL; 265 | tcp_close(server->pcb); 266 | return ERR_VAL; 267 | } 268 | //### if( server->clientPcb ) { 269 | //### printf("Overwriting server->clientPcb\n"); //### 270 | //### } 271 | server->clientPcb = clientPcb; 272 | return ERR_OK; 273 | } 274 | 275 | bool tcpServerStart(TCP_SERVER_T *server, int portNum) { 276 | server->pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); 277 | if( !server->pcb ) { 278 | return false; 279 | } 280 | 281 | if( tcp_bind(server->pcb, NULL, portNum) != ERR_OK ) { 282 | return false; 283 | } 284 | 285 | server->clientPcb = NULL; 286 | 287 | struct tcp_pcb *pcb = tcp_listen_with_backlog(server->pcb, 1); 288 | if( !pcb ) { 289 | if( server->pcb ) { 290 | tcp_close(server->pcb); 291 | server->pcb = NULL; 292 | } 293 | return false; 294 | } 295 | server->pcb = pcb; 296 | 297 | tcp_arg( server->pcb, server); 298 | tcp_accept(server->pcb, tcpServerAccept); 299 | tcp_err( server->pcb, tcpServerErr); 300 | 301 | return true; 302 | } 303 | 304 | uint16_t tcpWriteBuf(TCP_CLIENT_T *client, const uint8_t *buf, uint16_t len) { 305 | uint32_t ints; 306 | 307 | if( client && client->pcb && client->pcb->callback_arg ) { 308 | 309 | if( client->txBuffLen + len > TCP_CLIENT_TX_BUF_SIZE && client->connected ) { 310 | #ifndef NDEBUG 311 | gpio_put(TXBUFF_OVFL, HIGH); 312 | #endif 313 | while( client->txBuffLen + len > TCP_CLIENT_TX_BUF_SIZE && client->connected ) { 314 | tight_loop_contents(); 315 | } 316 | #ifndef NDEBUG 317 | gpio_put(TXBUFF_OVFL, LOW); 318 | #endif 319 | } 320 | // lock out the lwIP thread now so that it can't end up calling 321 | // tcpSend until we're done with it... really don't want two 322 | // threads messing with txBuff at the same time. 323 | cyw43_arch_lwip_begin(); 324 | for( uint16_t i = 0; i < len; ++i ) { 325 | client->txBuff[client->txBuffTail++] = buf[i]; 326 | if( client->txBuffTail == TCP_CLIENT_TX_BUF_SIZE ) { 327 | client->txBuffTail = 0; 328 | } 329 | ints = save_and_disable_interrupts(); 330 | ++client->txBuffLen; 331 | restore_interrupts(ints); 332 | } 333 | #ifndef NDEBUG 334 | if( client->txBuffLen > maxTxBuffLen ) { 335 | maxTxBuffLen = client->txBuffLen; 336 | } 337 | #endif 338 | if( client->txBuffLen && client->pcb && client->pcb->callback_arg && !client->waitingForAck ) { 339 | tcpSend(client); 340 | } 341 | cyw43_arch_lwip_end(); 342 | return len; 343 | } 344 | return 0; 345 | } 346 | 347 | uint16_t tcpWriteStr(TCP_CLIENT_T *client, const char *str) { 348 | return tcpWriteBuf(client, (uint8_t *)str, strlen(str)); 349 | } 350 | 351 | uint16_t tcpWriteByte(TCP_CLIENT_T *client, uint8_t c) { 352 | return tcpWriteBuf(client, (uint8_t *)&c, 1); 353 | } 354 | 355 | uint16_t tcpBytesAvailable(TCP_CLIENT_T *client) { 356 | if( client ) { 357 | return client->rxBuffLen; 358 | } 359 | return 0; 360 | } 361 | 362 | int tcpReadByte(TCP_CLIENT_T *client, int rqstTimeout = -1) { 363 | int c; 364 | uint32_t timeout = 0; 365 | uint32_t ints; 366 | 367 | if( client ) { 368 | if( rqstTimeout > 0 ) { 369 | timeout = millis() + rqstTimeout; 370 | } 371 | do { 372 | if( client->rxBuffLen ) { 373 | c = client->rxBuff[client->rxBuffHead++]; 374 | if( client->rxBuffHead == TCP_CLIENT_RX_BUF_SIZE ) { 375 | client->rxBuffHead = 0; 376 | } 377 | ints = save_and_disable_interrupts(); 378 | --client->rxBuffLen; 379 | restore_interrupts(ints); 380 | if( !client->rxBuffLen && client->totLen && client->pcb) { 381 | cyw43_arch_lwip_begin(); 382 | tcp_recved(client->pcb, client->totLen); 383 | client->totLen = 0; 384 | cyw43_arch_lwip_end(); 385 | } 386 | return c; 387 | } else { 388 | tight_loop_contents(); 389 | } 390 | } while( timeout > millis() ); 391 | } 392 | return -1; 393 | } 394 | 395 | uint16_t tcpReadBytesUntil(TCP_CLIENT_T *client, uint8_t terminator, char *buf, uint16_t max_len) { 396 | char *p = buf; 397 | uint16_t c; 398 | 399 | uint32_t timeout = millis() + 1000; 400 | if( max_len > 0 ) { 401 | do { 402 | if( client->rxBuffLen ) { 403 | c = tcpReadByte(client); 404 | if( c != terminator ) { 405 | *p++ = (char)c; 406 | --max_len; 407 | timeout = millis() + 1000; 408 | } else { 409 | break; 410 | } 411 | } else { 412 | tight_loop_contents(); 413 | } 414 | } while( max_len > 0 && timeout > millis() ); 415 | return p - buf; 416 | } 417 | return 0; 418 | } 419 | 420 | void tcpTxFlush(TCP_CLIENT_T *client) { 421 | if( client ) { 422 | while( client->pcb && client->connected && client->txBuffLen ) { 423 | tight_loop_contents(); 424 | } 425 | } 426 | } 427 | 428 | bool serverHasClient(TCP_SERVER_T *server) { 429 | return server->clientPcb != NULL; 430 | } 431 | 432 | TCP_CLIENT_T *serverGetClient(TCP_SERVER_T *server, TCP_CLIENT_T *client) { 433 | client->pcb = server->clientPcb; 434 | server->clientPcb = NULL; 435 | 436 | client->rxBuffLen = 0; 437 | client->rxBuffHead = 0; 438 | client->rxBuffTail = 0; 439 | client->totLen = 0; 440 | 441 | client->txBuffLen = 0; 442 | client->txBuffHead = 0; 443 | client->txBuffTail = 0; 444 | 445 | client->waitingForAck = false; 446 | 447 | tcp_arg( client->pcb, client); 448 | tcp_err( client->pcb, tcpClientErr); 449 | tcp_sent(client->pcb, tcpSent); 450 | tcp_poll(client->pcb, tcpPoll, 2); 451 | tcp_recv(client->pcb, tcpRecv); 452 | tcp_nagle_disable(client->pcb); // disable Nalge algorithm by default 453 | 454 | client->connected = true; 455 | client->connectFinished = true; 456 | 457 | return client; 458 | } 459 | -------------------------------------------------------------------------------- /src/wifi_modem.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Pico WiFi modem: a Pico W based RS232<->WiFi modem 3 | // with Hayes style AT commands and blinking LEDs. 4 | // 5 | // A "let's learn about the Pico W and lwIP" project. It 6 | // betrays its ESP8266 + Arduino IDE roots in its 7 | // structure; certainly no one would start a Pico 8 | // project from scratch and write it this way! 9 | // 10 | // Originally based on 11 | // Original Source Copyright (C) 2016 Jussi Salin 12 | // Additions (C) 2018 Daniel Jameson, Stardot Contributors 13 | // Additions (C) 2018 Paul Rickards 14 | // Additions 2020-2022 Wayne Hortensius 15 | // 16 | // This program is free software: you can redistribute it and/or modify 17 | // it under the tertms of the GNU General Public License as published by 18 | // the Free Software Foundation, either version 3 of the License, or 19 | // (at your option) any later version. 20 | // 21 | // This program is distributed in the hope that it will be useful, 22 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | // GNU General Public License for more details. 25 | // 26 | // You should have received a copy of the GNU General Public License 27 | // along with this program. If not, see . 28 | // 29 | #include 30 | #include 31 | #include 32 | 33 | #include "pico/stdlib.h" 34 | #include "pico/cyw43_arch.h" 35 | #include "hardware/watchdog.h" 36 | #include "hardware/i2c.h" 37 | #include "hardware/sync.h" 38 | 39 | #include "lwip/pbuf.h" 40 | #include "lwip/tcp.h" 41 | #include "lwip/dns.h" 42 | 43 | 44 | #include "wifi_modem.h" 45 | #include "globals.h" 46 | #include "eeprom.h" 47 | #include "tcp_support.h" 48 | #include "support.h" 49 | #include "at_basic.h" 50 | #include "at_extended.h" 51 | #include "at_proprietary.h" 52 | 53 | // ============================================================= 54 | void setup(void) { 55 | bool ok = true; 56 | 57 | stdio_init_all(); 58 | 59 | gpio_init(DTR); 60 | gpio_set_dir(DTR, INPUT); 61 | 62 | gpio_init(RI); 63 | gpio_set_dir(RI, OUTPUT); 64 | gpio_put(RI, !ACTIVE); // not ringing 65 | 66 | gpio_init(DCD); 67 | gpio_set_dir(DCD, OUTPUT); 68 | gpio_put(DCD, !ACTIVE); // not connected 69 | 70 | gpio_init(DSR); 71 | gpio_set_dir(DSR, OUTPUT); 72 | gpio_put(DSR, !ACTIVE); // modem is not ready 73 | #ifndef NDEBUG 74 | gpio_init(POLL_STATE_LED); 75 | gpio_set_dir(POLL_STATE_LED, OUTPUT); 76 | gpio_put(POLL_STATE_LED, LOW); 77 | 78 | gpio_init(RXBUFF_OVFL); 79 | gpio_set_dir(RXBUFF_OVFL, OUTPUT); 80 | gpio_put(RXBUFF_OVFL, LOW); 81 | 82 | gpio_init(TXBUFF_OVFL); 83 | gpio_set_dir(TXBUFF_OVFL, OUTPUT); 84 | gpio_put(TXBUFF_OVFL, LOW); 85 | #endif 86 | initEEPROM(); 87 | readSettings(&settings); 88 | 89 | if( settings.magicNumber != MAGIC_NUMBER ) { 90 | // no valid data in EEPROM/NVRAM, populate with defaults 91 | factoryDefaults(NULL); 92 | } 93 | sessionTelnetType = settings.telnet; 94 | 95 | uart_set_baudrate(uart0, settings.serialSpeed); 96 | uart_set_format(uart0, settings.dataBits, settings.stopBits, settings.parity); 97 | uart_set_translate_crlf(uart0, false); 98 | setHardwareFlow(settings.rtsCts); 99 | 100 | // enable interrupt when DTR goes inactive if we're not ignoring it 101 | gpio_set_irq_enabled_with_callback(DTR, GPIO_IRQ_EDGE_RISE, settings.dtrHandling != DTR_IGNORE, dtrIrq ); 102 | 103 | if( settings.startupWait ) { 104 | while( true ) { // wait for a CR 105 | if( uart_is_readable(uart0) ) { 106 | if( uart_getc(uart0) == CR ) { 107 | break; 108 | } 109 | } 110 | } 111 | } 112 | 113 | cyw43_arch_init(); 114 | cyw43_arch_enable_sta_mode(); 115 | // disable Wifi power management 116 | // if this is not done, after 5-10 minutes the Pico W does not 117 | // respond to incoming packets and can only be awoken by the 118 | // arrival of serial data 119 | cyw43_wifi_pm(&cyw43_state, CYW43_DEFAULT_PM & ~0xf); 120 | if( settings.ssid[0] ) { 121 | for( int i = 0; i < 4; ++i ) { 122 | cyw43_arch_wifi_connect_timeout_ms(settings.ssid, settings.wifiPassword, CYW43_AUTH_WPA2_AES_PSK, 10000); 123 | if( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP ) { 124 | break; 125 | } 126 | } 127 | } 128 | 129 | if( settings.listenPort ) { 130 | tcpServerStart(&tcpServer, settings.listenPort); 131 | } 132 | 133 | #if OTA_UPDATE_ENABLED 134 | if( settings.ssid[0] && cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP ) { 135 | setupOTAupdates(); 136 | } 137 | #endif 138 | 139 | if( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP || !settings.ssid[0] ) { 140 | if( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP ) { 141 | gpio_put(DSR, ACTIVE); // modem is finally ready or SSID not configured 142 | dns_init(); 143 | } 144 | if( settings.autoExecute[0] ) { 145 | strncpy(atCmd, settings.autoExecute, MAX_CMD_LEN); 146 | atCmd[MAX_CMD_LEN] = NUL; 147 | if( settings.echo ) { 148 | printf("%s\r\n", atCmd); 149 | } 150 | doAtCmds(atCmd); // auto execute command 151 | } else { 152 | sendResult(R_OK); 153 | } 154 | } else { 155 | sendResult(R_ERROR); // SSID configured, but not connected 156 | } 157 | } 158 | 159 | // ============================================================= 160 | void loop(void) { 161 | 162 | checkForIncomingCall(); 163 | 164 | if( settings.dtrHandling == DTR_RESET && checkDtrIrq() ) { 165 | resetToNvram(NULL); 166 | } 167 | 168 | switch( state ) { 169 | 170 | case CMD_NOT_IN_CALL: 171 | #if OTA_UPDATE_ENABLED 172 | if( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP ) { 173 | ArduinoOTA.handle(); 174 | } 175 | #endif 176 | inAtCommandMode(); 177 | break; 178 | 179 | case CMD_IN_CALL: 180 | inAtCommandMode(); 181 | if( state == CMD_IN_CALL && !tcpIsConnected(tcpClient) ) { 182 | endCall(); // hang up if not in a call 183 | } 184 | break; 185 | 186 | case PASSWORD: 187 | inPasswordMode(); 188 | break; 189 | 190 | case ONLINE: 191 | if( uart_is_readable(uart0) ) { // data from RS-232 to Wifi 192 | sendSerialData(); 193 | } 194 | 195 | while( tcpBytesAvailable(tcpClient) && !uart_is_readable(uart0) ) { 196 | // data from WiFi to RS-232 197 | int c = receiveTcpData(); 198 | if( c != -1 ) { 199 | uart_putc_raw(uart0, (char)c); 200 | } 201 | } 202 | 203 | if( escCount == ESC_COUNT && millis() > guardTime ) { 204 | state = CMD_IN_CALL; // +++ detected, back to command mode 205 | sendResult(R_OK); 206 | escCount = 0; 207 | } 208 | 209 | if( settings.dtrHandling != DTR_IGNORE && checkDtrIrq() ) { 210 | switch( settings.dtrHandling ) { 211 | 212 | case DTR_GOTO_COMMAND: 213 | state = CMD_IN_CALL; 214 | sendResult(R_OK); 215 | escCount = 0; 216 | break; 217 | 218 | case DTR_END_CALL: 219 | endCall(); 220 | break; 221 | 222 | case DTR_RESET: 223 | resetToNvram(NULL); 224 | break; 225 | } 226 | } 227 | 228 | if( !tcpIsConnected(tcpClient) ) { // no client? 229 | endCall(); // then hang up 230 | } 231 | break; 232 | } 233 | } 234 | 235 | // ============================================================= 236 | void doAtCmds(char *atCmd) { 237 | size_t len; 238 | 239 | trim(atCmd); // get rid of leading and trailing spaces 240 | if( atCmd[0] ) { 241 | // is it an AT command? 242 | if( strncasecmp(atCmd, "AT", 2) ) { 243 | sendResult(R_ERROR); // nope, time to die 244 | } else { 245 | // save command for possible future A/ 246 | strncpy(lastCmd, atCmd, MAX_CMD_LEN); 247 | lastCmd[MAX_CMD_LEN] = NUL; 248 | atCmd += 2; // skip over AT prefix 249 | len = strlen(atCmd); 250 | 251 | if( !atCmd[0] ) { 252 | // plain old AT 253 | sendResult(R_OK); 254 | } else { 255 | trim(atCmd); 256 | while( atCmd[0] ) { 257 | if( !strncasecmp(atCmd, "?", 1) ) { // help message 258 | // help 259 | atCmd = showHelp(atCmd + 1); 260 | } else if( !strncasecmp(atCmd, "$AYT", 4) ) { 261 | // send Telnet "Are You There?" 262 | atCmd = doAreYouThere(atCmd + 4); 263 | } else if( !strncasecmp(atCmd, "$SB", 3) ) { 264 | // query/set serial speed 265 | atCmd = doSpeedChange(atCmd + 3); 266 | } else if( !strncasecmp(atCmd, "$SU", 3) ) { 267 | // query/set serial data configuration 268 | atCmd = doDataConfig(atCmd + 3); 269 | } else if( !strncasecmp(atCmd, "$SSID", 5) ) { 270 | // query/set WiFi SSID 271 | atCmd = doSSID(atCmd + 5); 272 | } else if( !strncasecmp(atCmd, "$PASS", 5) ) { 273 | // query/set WiFi password 274 | atCmd = doWiFiPassword(atCmd + 5); 275 | } else if( !strncasecmp(atCmd, "C", 1) ) { 276 | // connect/disconnect to WiFi 277 | atCmd = wifiConnection(atCmd + 1); 278 | } else if( !strncasecmp(atCmd, "D", 1) && len > 2 && strchr("TPI", toupper(atCmd[1])) ) { 279 | // dial a number 280 | atCmd = dialNumber(atCmd + 2); 281 | } else if( !strncasecmp(atCmd, "DS", 2) && len == 3 ) { 282 | // speed dial a number 283 | atCmd = speedDialNumber(atCmd + 2); 284 | } else if( !strncasecmp(atCmd, "H0", 2) ) { 285 | // hang up call 286 | atCmd = hangup(atCmd + 2); 287 | } else if( !strncasecmp(atCmd, "H", 1) && !isdigit(atCmd[1]) ) { 288 | // hang up call 289 | atCmd = hangup(atCmd + 1); 290 | } else if( !strncasecmp(atCmd, "&Z", 2) && isdigit(atCmd[2]) ) { 291 | // speed dial query or set 292 | atCmd = doSpeedDialSlot(atCmd + 2); 293 | } else if( !strncasecmp(atCmd, "O", 1) ) { 294 | // go online 295 | atCmd = goOnline(atCmd + 1); 296 | } else if( !strncasecmp(atCmd, "GET", 3) ) { 297 | // get a web page (http only, no https) 298 | atCmd = httpGet(atCmd + 3); 299 | } else if( settings.listenPort && !strncasecmp(atCmd, "A", 1) && serverHasClient(&tcpServer) ) { 300 | // manually answer incoming connection 301 | atCmd = answerCall(atCmd + 1); 302 | } else if( !strncasecmp(atCmd, "S0", 2) ) { 303 | // query/set auto answer 304 | atCmd = doAutoAnswerConfig(atCmd + 2); 305 | } else if( !strncasecmp(atCmd, "S2", 2) ) { 306 | // query/set escape character 307 | atCmd = doEscapeCharConfig(atCmd + 2); 308 | } else if( !strncasecmp(atCmd, "$SP", 3) ) { 309 | // query set inbound TCP port 310 | atCmd = doServerPort(atCmd + 3); 311 | } else if( !strncasecmp(atCmd, "$BM", 3) ) { 312 | // query/set busy message 313 | atCmd = doBusyMessage(atCmd + 3); 314 | } else if( !strncasecmp(atCmd, "&R", 2) ) { 315 | // query/set require password 316 | atCmd = doServerPassword(atCmd + 2); 317 | } else if( !strncasecmp(atCmd, "I", 1) ) { 318 | // show network information 319 | atCmd = showNetworkInfo(atCmd + 1); 320 | } else if( !strncasecmp(atCmd, "Z", 1) ) { 321 | // reset to NVRAM 322 | atCmd = resetToNvram(atCmd + 1); 323 | } else if( !strncasecmp(atCmd, "&V", 2) ) { 324 | // display current and stored settings 325 | atCmd = displayAllSettings(atCmd + 2); 326 | } else if( !strncasecmp(atCmd, "&W", 2) ) { 327 | // write settings to EEPROM 328 | atCmd = updateNvram(atCmd + 2); 329 | } else if( !strncasecmp(atCmd, "&D", 2) ) { 330 | // DTR transition handling 331 | atCmd = doDtrHandling(atCmd + 2); 332 | } else if( !strncasecmp(atCmd, "&F", 2) ) { 333 | // factory defaults 334 | atCmd = factoryDefaults(atCmd); 335 | } else if( !strncasecmp(atCmd, "E", 1) ) { 336 | // query/set command mode echo 337 | atCmd = doEcho(atCmd + 1); 338 | } else if( !strncasecmp(atCmd, "Q", 1) ) { 339 | // query/set quiet mode 340 | atCmd = doQuiet(atCmd + 1); 341 | } else if( !strncasecmp(atCmd, "RD", 2) 342 | || !strncasecmp(atCmd, "RT", 2) ) { 343 | // read time and date 344 | atCmd = doDateTime(atCmd + 2); 345 | } else if( !strncasecmp(atCmd, "V", 1) ) { 346 | // query/set verbose mode 347 | atCmd = doVerbose(atCmd + 1); 348 | } else if( !strncasecmp(atCmd, "X", 1) ) { 349 | // query/set extended result codes 350 | atCmd = doExtended(atCmd + 1); 351 | } else if( !strncasecmp(atCmd, "$W", 2) ) { 352 | // query/set startup wait 353 | atCmd = doStartupWait(atCmd + 2); 354 | } else if( !strncasecmp(atCmd, "NET", 3) ) { 355 | // query/set telnet mode 356 | atCmd = doTelnetMode(atCmd + 3); 357 | } else if( !strncasecmp(atCmd, "$AE", 3) ) { 358 | // do auto execute commands 359 | atCmd = doAutoExecute(atCmd + 3); 360 | } else if( !strncasecmp(atCmd, "$TTY", 4) ) { 361 | // do telnet terminal type 362 | atCmd = doTerminalType(atCmd + 4); 363 | } else if( !strncasecmp(atCmd, "$TTL", 4) ) { 364 | // do telnet location 365 | atCmd = doLocation(atCmd + 4); 366 | } else if( !strncasecmp(atCmd, "$TTS", 4) ) { 367 | // do telnet location 368 | atCmd = doWindowSize(atCmd + 4); 369 | } else if( !strncasecmp(atCmd, "&K", 2) ) { 370 | // do RTS/CTS flow control 371 | atCmd = doFlowControl(atCmd + 2); 372 | } else if( !strncasecmp(atCmd, "$MDNS", 5) ) { 373 | // handle mDNS name 374 | atCmd = doMdnsName(atCmd + 5); 375 | } else { 376 | // unrecognized command 377 | sendResult(R_ERROR); 378 | } 379 | trim(atCmd); 380 | } 381 | } 382 | } 383 | } 384 | } 385 | 386 | int main(void) { 387 | setup(); 388 | while( true ) { 389 | loop(); 390 | } 391 | return 0; 392 | } 393 | 394 | -------------------------------------------------------------------------------- /src/wifi_modem.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODEM_H 2 | #define _MODEM_H 3 | 4 | #define DEBUG 0 5 | #define DEFAULT_SPEED 9600 6 | 7 | #define RING_INTERVAL 1500 8 | #define MAX_CMD_LEN 256 9 | #define TX_BUF_SIZE 256 10 | #define ESC_CHAR '+' 11 | #define ESC_COUNT 3 12 | #define GUARD_TIME 1000 13 | #define MAGIC_NUMBER 0x5678 14 | #define MAX_SSID_LEN 32 15 | #define MAX_WIFI_PWD_LEN 64 16 | #define DEFAULT_LISTEN_PORT 6400 17 | #define TELNET_PORT 23 18 | #define HTTP_PORT 80 19 | #define SPEED_DIAL_SLOTS 10 20 | #define MAGIC_ANSWER_RINGS 3 21 | #define MAX_ALIAS_LEN 16 22 | #define MAX_SPEED_DIAL_LEN 50 23 | #define MAGIC_SPEED_LEN 7 24 | #define MAX_MDNSNAME_LEN 80 25 | #define MAX_BUSYMSG_LEN 80 26 | #define MAX_PWD_LEN 80 27 | #define PASSWORD_TIME 60000 28 | #define PASSWORD_TRIES 3 29 | #define MAX_AUTOEXEC_LEN 80 30 | #define MAX_TERMINAL_LEN 80 31 | #define MAX_LOCATION_LEN 80 32 | 33 | #define NUL '\x00' 34 | #define CTLC '\x03' 35 | #define BS '\x08' 36 | #define LF '\x0A' 37 | #define CR '\x0D' 38 | #define DEL '\x7F' 39 | 40 | #define NO_TELNET ((uint8_t)0) 41 | #define REAL_TELNET ((uint8_t)1) 42 | #define FAKE_TELNET ((uint8_t)2) 43 | 44 | // Telnet codes 45 | #define VLSUP ((uint8_t)0) 46 | #define VLREQ ((uint8_t)1) 47 | #define LOC ((uint8_t)23) 48 | #define TTYPE ((uint8_t)24) 49 | #define NAWS ((uint8_t)31) 50 | #define TSPEED ((uint8_t)32) 51 | #define LFLOW ((uint8_t)33) 52 | #define LINEMODE ((uint8_t)34) 53 | #define XDISPLOC ((uint8_t)35) 54 | #define NEW_ENVIRON ((uint8_t)39) 55 | #define BINARY ((uint8_t)0) 56 | #define ECHO ((uint8_t)1) 57 | #define SUP_GA ((uint8_t)3) 58 | #define SE ((uint8_t)240) 59 | #define DM ((uint8_t)242) 60 | #define BRK ((uint8_t)243) 61 | #define AYT ((uint8_t)246) 62 | #define SB ((uint8_t)250) 63 | #define WILL ((uint8_t)251) 64 | #define WONT ((uint8_t)252) 65 | #define DO ((uint8_t)253) 66 | #define DONT ((uint8_t)254) 67 | #define IAC ((uint8_t)255) 68 | 69 | #define NIST_HOST "time.nist.gov" 70 | #define NIST_PORT 13 71 | 72 | #define ACTIVE LOW // RS232 control signals are active low 73 | 74 | #define RTS 2 // (GPIO02) input 75 | #define CTS 3 // (GPIO03) output 76 | #define DCD 4 // (GPIO04) output 77 | #define DSR 5 // (GPIO05) output 78 | #define DTR 6 // (GPIO06) input 79 | #define RI 7 // (GPIO07) output 80 | 81 | #define OUTPUT true 82 | #define INPUT false 83 | #define HIGH true 84 | #define LOW false 85 | 86 | // I2C EEPROM definitions 87 | #define I2C_ADDR 0x50 88 | #define I2C_SDA 16 89 | #define I2C_SCL 17 90 | #define I2C_BAUD 100000 91 | 92 | #define TCP_CLIENT_RX_BUF_SIZE 20000 93 | #define TCP_CLIENT_TX_BUF_SIZE 1100 94 | 95 | #ifndef NDEBUG 96 | #define POLL_STATE_LED 8 97 | #define RXBUFF_OVFL 9 98 | #define TXBUFF_OVFL 10 99 | #endif 100 | 101 | #endif 102 | --------------------------------------------------------------------------------