In recent blog posts I've got the telephony and text messaging software working. What isn't there yet, is making it all talk to the cellular modem -- so that's what we're going to finish here.
So let's start by getting some hardware organised that can talk to the cellular modem. We're prototyping using a real MEGA65 mainboard, so we need to tweak a build for that, which has two buffered UARTs exposed on the PMOD ports: One to talk to the low-power FPGA that manages sub-system power, and the other that talks to the UART of the cellular modem.
But even before we get to that point, we can get the communications with the cellular modem in hand, using a USB UART adaptor from Linux. So let's do that.
The key things we need to do are:
1. Setup basic modem operating parameters
2. Configure the modem to say RING when the phone rings.
3. Configure the modem to issue a +QIND message whenever an SMS message is received, or the call state changes, e.g., pick-up, hang-up, ringing etc.
4. Retrieve the first queued SMS message if there are SMS messages pending.
5. Send an SMS to an indicated number.
6. Retrieve network time, name and signal strength information.
Let's go through those one by one and implement them.
But first, let's get that modem plugged in and powered up, and confirm that we have the UART relay through the low-power FPGA working:
So what we have here is the cellular modem development board connected to the USB UART (that is pretending to be the MEGA65 right now), with the TX line from the cellular modem (green) relaying through the low-power FPGA (yellow) so that it can monitor messages from the modem to auto-wake the main FPGA when required. The TX line from the "MEGA65" goes direct to the RX line on the cellular modem's UART (blue). And apart from that, we have GND (orange).
And as we can see in the screenshot above, we can talk to the modem.
I've also bought and installed a pre-paid SIM card for testing, although it seems to be taking a while to activate, which is annoying, as I'd like to make a test call.
So we can start working on a simple library to do the things we need to do with the modem.
Hmm.. Turns out the firmware on this module needs updating to support VoLTE with Optus. But I can still work on the SMS processing commands in the meantime.
For that we have AT+CMGL=4 that will list all unread SMS messages, AT+GMD=n that will delete a specific message, as well as commands to read a specific message. What is lacking, but would have been nice, is a command that returns the _number_ of SMS messages. I can approximate it with a list, but that's a bit annoying.
Complicating matters is that saving an SMS message takes a second or two if we index it. So we'll still want to AT+CMGR to read a message when we want to store it.
So let's start by fleshing out modem_poll() so that it indicates if it has returned a line from the modem, and have it count the number of +CGML lines seen, and also if it's seen an OK or ERROR line, so that we know when it's done. That way a call to get the number of SMS messages yet to be processed can simply call modem_poll() until it sees an OK or ERROR message, or some sensible timeout occurs.
Got all that. Now getting ChatGPT to implement a small SMS PDU decoder. This turns out to be more complicated than I'd like, but not absurdly so. Just pushing ChatGPT with each decoding error I see and getting it to fix them one by one. In theory I can now decode an SMS into a UTF8 string.
Okay, got that working. Now getting it to write me the opposite that can take a UTF8 string and prepare it for sending as one or more SMS messages. That seems to be okay, but now the actual sending the SMS is getting a +CMS ERROR: 304, which means the modem isn't in PDU mode -- but I have set it. So maybe it is botching the message construction after all.
The bug turned out to be my fault, not ChatGPT's: I was putting a CR/LF sequence after the PDU before sending CTRL-Z. With that fixed, and a few other minor things, I can now send short SMS, long SMS, SMS with emojis etc, and it all arrives correctly :)
There is an intermittent protocol lock-up that I'd like to get to the bottom of, but it fundamentally works :)
So SMS deletion is the next frontier, and one that should be super easy in comparison.
But before I can tackle that, I've hit a problem where if there are too many SMS messages, the AT+CGML=4 command seems to truncate output, and doesn't print OK at the end. So I've added a timeout to that.
With that fixed, the good news is that we can even delete SMS messages.
The bad news is that the message numbers don't pack or shuffle down after a lower number message has been deleted.
So we probably need a command that returns the oldest SMS message, including it's number, so that we can then ask for it to be deleted after.
Okay, we have this working now:
$ bin/modem /dev/ttyUSB1 115200 init smsnext
INFO: Decoded SMS message #1:
Sender: +61434595174
Send time: 0000/00/00 00:00.00 (TZ+0min)
text: Honey
concat: 0
concat_ref: 0
concat_total: 0
concat_seq: 0
$ bin/modem /dev/ttyUSB1 115200 init smsdel=1
$ make bin/modem && bin/modem /dev/ttyUSB1 115200 init smsnext
INFO: Decoded SMS message #2:
Sender: 121
Send time: 0000/00/00 00:00.00 (TZ+0min)
text: Welcome to Voicemail! You have 3 new message(s). Please dial 121 to access messages.
concat: 0
concat_ref: 0
concat_total: 0
concat_seq: 0
$
In short, we can receive SMS messages in order, and then delete them.
So let's watch this all working together, sending and receiving SMS. I'm filming with my mobile phone, so I can't show them being received on my phone directly.
Milestone Checklist
So that completes the SMS part of our API, which satisfies these milestones:
q. 1.5 Text messaging software: Communications With Cellular Modem: Requirements Specifications
The requirements for this module ended up being able to be reduced to the very simple set of routine's we explored above: (1) Get number of unread SMS; (2) Read and SMS message; (3) Delete a received SMS message; and (4) Send an SMS.
We ended up going beyond this, by implementing some stretch goals, in particular: (5) Parse Unicode and Emoji-containing SMS; (6) Construct and send Unicode and Emoji-containing SMS; (7) Send multi-part SMS.
r. 1.5 Text messaging software: Communications With Cellular Modem: Implementation
The implementation is described and shown in the video above, as well as embodied in the source code, in particular in these files:
https://github.com/MEGA65/megaphone-modular/blob/main/src/telephony/README.md
https://github.com/MEGA65/megaphone-modular/blob/main/src/telephony/smsdecode.c
https://github.com/MEGA65/megaphone-modular/blob/main/src/telephony/smsdecode.h
https://github.com/MEGA65/megaphone-modular/blob/main/src/telephony/smsencode.c
https://github.com/MEGA65/megaphone-modular/blob/main/src/telephony/utf.c
https://github.com/MEGA65/megaphone-modular/blob/main/src/telephony/modem.c
https://github.com/MEGA65/megaphone-modular/blob/main/src/telephony/modem.h
s. 1.5 Text messaging software: Communications With Cellular Modem: Testing
t. 1.5 Text messaging software: Communications With Cellular Modem: Revision
The blog post text and video above shows the result of testing and iterative revision until a working module was obtained.
Okay, so now it's on to finishing the cellular modem telephony control module... If only Quectel had already responded with the firmware update I need for the modem for VoLTE on Australian networks...


No comments:
Post a Comment