-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Polishing the library #37
base: master
Are you sure you want to change the base?
Conversation
- Note comments are not up to date yet! I'll add them later and in doxygen style. Also in the header where they belong
This constant indicates that the desired index when writing to or reading from the buffer should be chosen automatically. This in short means that it continues to read or write where it left of.
Both Serial and I2C are streams. So the actual implementation can be moved to a common class (`StreamTransfer`) and the actual headers with the classes in question are just aliases and also include the respective header (`HardwareSerial.h` for `SerialTransfer` and `Wire.h` for `I2CTransfer`
- Removed debugging because that's not portable
- Also improved the signature for the callbacks - Added virtual destructor (would've been added regardless of if it was implemented specifically or not)
Now ignoring documentation this PR is finished. One thing that could make sense to do is updating the examples. Do you want them updated in this PR or should I make a separate PR for that? |
Currently the table prints as: ``` 00 9b ad 36 c1 5a 6c f7 19 82 b4 2f d8 43 75 ee 32 a9 9f 04 f3 68 5e c5 2b b0 86 1d ea 71 47 dc 64 ff c9 52 a5 3e 08 93 7d e6 d0 4b bc 27 11 8a 56 cd fb 60 97 0c 3a a1 4f d4 e2 79 8e 15 23 b8 ``` (Crosschecking with your original implementation this seems to be correct. Would be awesome if you could doublecheck it though)
Ok. I take it back. I found a way to make the CRC array compile time constant. |
Here's a little library I drafted up for that purpose: https://github.com/BrainStone/CppCompiletimeArrayGenerator What's your take on this? |
If it's only going to be applied to PacketCRC and no other sub-lib, let's just go with the private struct option. Also, how do I test your code without merging? I thought you were doing the work on your fork, but I don't think that's the case. Lastly, there are a lot of changes across the lib files so I can't easily tell: did the sketch-level API(s) change, thus requiring example sketch updates like you say or did you simply want to reformat them? I'd prefer to keep the existing API the same (adding to it is fine, however) |
Also, sorry about the squash thing - I'm not a professional software developer. Thank you for the insights, I'm learning a lot! |
As far as it seems it's only needed in PacketCRC. While I think that little lib is useful I don't think it belongs here. So a private struct and copying the code over seems to make the most sense
I am actually maintaing my own fork. See the line under the PR title: https://github.com/BrainStone/SerialTransfer/tree/inheritance
Well it's mostly the same. I did some cleanups here and there, some types changed, some renaming for consitency. So while the examples might need some minor adjustments, nothing major has changed. Like the way the lib works hasn't changed. Just some names In any case, I'll make sure that the examples will be updated one way or another (unless you insist on doing it yourself).
No hard feelings. It was just a bit of a hassle having to rebase the branch locally. |
I looked over everything and it looks good. Since you know the new source code better, you should update the examples. I'll do the acceptance testing on my hardware and merge when ready. |
CRC table: ``` 00 9b ad 36 c1 5a 6c f7 19 82 b4 2f d8 43 75 ee 32 a9 9f 04 f3 68 5e c5 2b b0 86 1d ea 71 47 dc 64 ff c9 52 a5 3e 08 93 7d e6 d0 4b bc 27 11 8a 56 cd fb 60 97 0c 3a a1 4f d4 e2 79 8e 15 23 b8 ``` Live example: https://godbolt.org/z/dz3qWT
Thanks, everything compiles fine now
I'll look into what might be going wrong with SPI and I2C |
I2C:While the TwoWire class inherits from the Stream class, there are a couple of TwoWire members needed for access by this library. These required members include: // sets function called on slave write
void TwoWire::onReceive( void (*function)(int) ) void TwoWire::beginTransmission(uint8_t address) and uint8_t TwoWire::endTransmission(uint8_t sendStop) SPI:For SPI, the slave needs to somehow be properly configured with Also, I noticed your code attempts to write multiple bytes per SerialTransfer/src/SPITransfer.cpp Lines 72 to 90 in 64fc4ea
|
Do you really need the Now also an interesting question for both SPI and I2C is if they are operating in slave or master mode. Because admittedly the way both are implemented it's assumed they are master. I'll have a little think about how I manage the master slave dilemma. Your input on the matter would be greatly aprechiated. And it's important because both master and slave can send and receive data and frankly both should be able to. |
Yes, I've done some testing on my own and
Maybe in terms of the library's perspective, but at the sketch level, users are expected to know and configure their Arduino appropriately. I don't think that's necessarily the best way to do it, but it was the easiest way to get it to work originally.
Yes, the master/slave concept is an odd problem-set to deal with for this library. While it may be more difficult, I think it would be best for the Note that there may be some things the users will have to implement at the sketch level to get things to work. |
We also need to add another board (ESP8266) to the following processor exclusion conditions and readme disclaimer: SerialTransfer/src/SPITransfer.h Line 5 in 64fc4ea
SerialTransfer/src/SPITransfer.cpp Line 3 in 64fc4ea
|
Also allowed manually overriding whether or not SPI is enabled with a macro.
Taken care of the SPI thing. And I like the idea of letting the user chose whether or not the library is in slave mode or not. |
This is to allow single writes in the writeBytes methods. This is required for I2C. Sadly since you can't make single members public or private, `txBuff` needs to be a reference
Forcing the struct to be oacked removes any potential padding, meaning the two arrays are gurantueed to be next to eachother.
Seems very good lib, even though I'll test it in UART but uses lots of memory almost half of the memory of 328 and all of the 168. Not much left for other parts of the code. |
It (in this version) should use a bit more than 1kb of ROM and 300 bytes of RAM. What numbers are you seeing? |
Sketch uses 5678 bytes (18%) of program storage space. Maximum is 30720 bytes. Am I using the wrong one? |
this is results of the compiling the uart_rx example by the way. |
That looks fine to me.
I'm not sure which version you downloaded, so I can't tell. |
5,6Kb does not a big deal, but it would be good to consider to try to reduce the dynamic memory. 955 bytes lots for just transferring structured data. |
Again, this has been worked on. If you use the code present in this PR it should be lower. |
What is the status of this PR? Many thanks @BrainStone @PowerBroker2 |
I've more or less decided to forge on ahead improving the master branch since I couldn't easily grasp what exactly is being updated with this PR. However, that doesn't mean I've given up on it (else I would close it) - maybe I'll revisit sometime in the near future... @brunojoyal In the mean time, is there any bug you've discovered or have a feature in mind you would like to see in the master branch? |
Thanks a lot for asking, that is nice of you. I am using this library for one of my projects, to transfer photos (roughly 100kb in size) via UART. There is nothing specifically in this pull request that I was looking forward to; mainly I was curious to know the status and direction of development since my project depends on it. To transfer 100kb files I implemented a small file-transfer protocol using your library. I have a DEVKIT v1 acting as a master and ESPCAM acting as a slave. When at rest, the ESPCAM is listening for SerialTransfer packets which are simply commands encoded in the Packet ID. When it receives a photo request command, it goes to work taking a picture and then sending it over to the master in numbered chunks. It works pretty well considering how primitive it is - perhaps I will make it into its own library. In any case, kudos to you for putting this together, it's been fun to use. Perhaps it would make sense to have a method to end the transfer? As things are now, I am calling transfer.begin during setup, and my transfer object is then active forever. For the slave, which has to wait to commands, this makes sense. But for the master, it would make more sense to call transfer.begin when a message must be sent or when a message is expected, and to call transfer.end when the message ends. This way, every new transfer starts with a fresh buffer. My greatest difficulty has been to recover gracefully from failed transfers. When a packet fails to be received, sometimes trying to send it almost immediately again works, but sometimes it seems to fail repeatedly until I let the serial buffer time out and/or try enough times. I suspect it is because the remnants of the failed packet sometimes still populate the packet buffer and mess up each new incoming packet. Or something... Aside from a transfer.end method, another feature which could help keep the buffers clean is some kind of timeout option (separate from the UART buffer timeout): if the whole packet is not successfully received within TIMEOUT μs, then it is marked as a failure and the packet is reset. What do you think? I hope I'm not trying to reinvent the wheel. Perhaps there are better ways to deal with these things. Please do let me know. In any case, good work! Oh and one more minor thing, perhaps available() should be called something else, maybe process() or tick()? My feeling comes from the fact that calling available() twice in a row should not destroy anything. As it stands, it crushes any packet received during the first available() call, contrasting with the available() method of the Stream class. |
Please take a look at https://github.com/brunojoyal/SerialTransfer. I should say that I am using an unshielded unstranded 4-conductor wire to carry both 5V DC and the UART lines, so my serial is prone to error. Please let me know what you think! |
That sounds like a cool project! I'm glad you've found my lib useful. While I'm not doing a whole lot with it right now, it is still very much maintained and active.
I'm not sure how useful a
Yeah, I'm not sure why this would be an issue, however, I don't think it resets the packet parsing if it comes into contact with a new start byte - I should look into that...
Yeah, I think this would be a good feature!
I've never seen anyone call
Looks cool! I do have a couple of small edits, but I think you're good to submit a PR as-is. I'll merge and make the small changes I had in mind (nothing big). I am planning on making that |
Thanks a lot for your feedback and comments and for your timely response. I've submitted a PR with the changes. Cheers! |
And I forgot to say, this seems like just what I need! |
I forgot to mention that the lib already has a SerialTransfer/src/SerialTransfer.cpp Lines 123 to 143 in 3458920
|
@brunojoyal Take a look at my edits and test them in your project to see if it works. You can clone the current main branch for the latest code. If your tests are successful, I'll tag out a new version. |
@PowerBroker2 , I am testing it right now, and it is working like a charm. A considerable improvement since two days ago. Many thanks! |
@PowerBroker2 Just an update - my current app has been up for 28 hours, during which it successfully transferred 1345 pictures of roughly 185kb each, with a success rate of 97%. Good stuff!! |
As of right now this a is work in progress though I believe you might want to watch my progress.
TODO:
Packet
classSerialTransfer
class (will also get an aliasStreamTransfer
to indicate that it can work with any type ofStream
)SPITransfer
I2CTransfer
PacketCRC
Packet
PacketCRC
SerialTransfer
SPITransfer
IC2Transfer