⬆️ ⬇️

To the issue of trends

"If you do not know where to start, start over again, most likely you will not go wrong."


So, at first there was (there is not a word, but many words) a topic on one of the sites devoted to amateur electronics design and programming (who said “Arduino” - to leave the class), I will not call it, since this topic could be raised on any The site of such a profile was dedicated to the slow work of a certain library (we will not point with a finger, although it was a Baby Elephant, namely LiquidDisplayI2C) on a specific hardware platform. The topic seemed interesting (my regular readers already understood that speed is my fad) and, because discussing it (as often happens on such resources) quickly turned into throwing bananas and figuring out who is really cool macho, and who is a minute went by and the technical side turned into a vanishingly small amount, an independent study of this issue was undertaken, during which several interesting circumstances emerged that are offered to the attention of a respected public.



To clarify the problem under study, it is necessary to establish interaction with a device using a parallel interface (in this case it was an indicator 1602, although it could be another device), using as few MK legs as possible. Since the interaction through 0 (zero) legs seems to me to be a poorly feasible approach, the 1 (one) foot should be considered the necessary minimum.



Such implementations take place, it suffices to recall WS2181, but since the only reasonably implementable method of encoding information is time manipulation, the speed of this approach will be far from ideal. We know numerous successful implementations of this approach, among which USB and Ethernet interfaces are particularly noteworthy - fast single-wire interfaces, but we can hardly use them with minimal costs and relatively simple hardware but very slow 1wire.



The situation changes drastically if we begin to use 2 (two) legs, which allows us to use the classical scheme with separation of the clock signal and data, which allows us to increase the speed without significant hardware costs. The real candidates are SPI in transmit mode and I2C. Unfortunately, in real life, the first one is not two-wire, and one or more pins are strongly needed to select a particular device, or we must cascade devices with a corresponding reduction in channel capacity. In addition, SPI is not a channel with guaranteed delivery at the hardware level, which is not always (more precisely, always not) convenient. In this regard, the second candidate is preferable, since it has built-in means of addressing and transmission control. The only drawback is a lower transmission rate (100 kHz or 400 kHz in fast mode against units and even tens of MHz), but you have to pay for everything in this world. Moreover, taking into account the peculiarities of the device being connected, for visualization of speed information even at 100 kHz ~ 10 kilobytes per second should suffice (quite comparable with the speed of 9600, which quite provided a fairly fast picture on the display 24 * 80). Both interfaces are included in the standard set of almost all MCs, if for some reason we cannot use hardware resources, they are easily implemented on ordinary pins, again with a certain decrease in performance or an increase in the processor load. So the choice of the I2C interface can be considered quite justified and reasonable for our task.

')

Next comes the question of choosing a converter chip, since the interfaces are fixed on both sides, we need the so-called I2C port extender, this chip is provided by the NXP and is called PCF8574. MCh is affordable, widely represented on the market and on its basis a board has already been built for interfacing with the display interface taking into account the design features of the device, so this choice is quite justified, there is one feature, but more on that later.



In the meantime, I would like to tell the world about the first surprise, it is associated with the choice of chip. The fact is that in addition to the specified company, TI does the same as the MSC, with the same designation. Moreover, the layout of the legs for at least three types of enclosures (DIP16, SO16, SSOP20) is identical for both firms. It seems that everything is good, it is always pleasant to have a second supplier, but the devil is hiding in details and pay attention to them. For a start, let's look at the documentation on the NXP chip, where everything is clearly and clearly written, the algorithm of the serial interface is fully consistent with the standard. We draw attention to the fact that we can repeatedly record data in one session of communication, which will be very useful later. Let us also pay attention to page 14 of the description, where we are given ways to improve performance by migrating to other types of microcircuits (this one has a limitation of 100 kHz). In summary, thanks to the firm for such intelligible and comprehensive documentation.



Well, now about the sad. We open the documentation on the TI production microcircuit and everything started to turn around ... Actually, I went there to clarify the misunderstandings with the highest possible frequency of exchange, since the forum posts that it is possible to increase the frequency of exchange to 400 kgHz and even 800 kHz, with a note that in fact it was 640 kHz, but for some reason it did not earn 1 MHz, I was somewhat alarmed, since the documentation from NXP clearly indicated the maximum exchange frequency of 100 kHz, and I always treat with great disapproval the attempts to go beyond the TU well such a change i wont Therefore, suggested that the TI option may be faster. It turned out that this is not the case and his work is also guaranteed only at a standard speed of 100 kHz, which is clearly spelled out. Further, I was somewhat surprised by the presence of calculations of load resistors for fast mode, in addition to the standard one, but apparently, this section just wanders through the documentation for chips related to I2C and this reference section does not promise us anything. Somewhat reminiscent of a joke about fish and fleas, but not fatal.



But then my eye fell on page 12, where the description of the features of functioning begins. And we find funny wording “The data byte is accompanied by a confirmation signal issued by the device. If other data bytes are transmitted by the master, followed by acknowledgment, they are ignored by the instrument. The data is output only if the total number of bytes is received and confirmed. ”- if I was mistaken with the translation, it is not much. It sounds somewhat incomprehensible - how many bytes will make up the full amount and what will happen if they are not issued by the master? Fortunately, on page 13 there is a timeline that is meant to clarify, since one good temporary page will replace the description pages. But not in this case - firstly, it is clear that the next byte is not ignored, but at least confirmed by the device, which is hinted as if in the text. Further, we see that the data in the second byte is clearly relevant to the output, since the bits in it have the same designation as in the first, namely, P0-P7. Third, it is after receiving the second byte that the data is output to the parallel port, which for some reason is designated as B, and not P, as was all the previous description. For reasons that are not clear, the value on port A, which is intended to set the variable part of the device address, changes along with the output data. Particularly pleased with the interrupt signal, which is set at the end of the cycle and apparently remains high forever, until the power is removed from the device. And now we ask the question - what is this unknown garbage, I have no other definition for what I saw (however, there is, this is “thrash, waste and sodomy”). Why do we need the second byte, where it came from at all, if we have one output port, what should be in it, why in the first byte the 5th bit must necessarily be 1, what happens if the second byte is not sent and many other interesting questions.



I must say right away that I have no answers to these questions, I am on the shaky ground of conjectures and assumptions, and I don’t understand why a respected company needed to drive me there. I see a number of contradictory statements that lead us to recall the famous anecdote about three turtles (or ants), of which not all adhere to the truth. We will try to solve this charade, although we are not obliged to do this, as my first boss said after the institute: “When you do something during work hours that you are not paid for, you don’t do what you get paid for,” but I write This post is after hours, so forgive me such a distraction from work.

The first option is more attractive for me personally - in fact, the microcircuit functions exactly the same way as her NXP girlfriend, and all the misunderstandings arose due to Krivoruk’s technical writers who erroneously translated the timeframe from its 16-bit pcf8575 device into this device. more to her, too, there are questions and exactly the same. Then the devices of different companies are compatible and everything is fine, you just need to use the correct description and for the wrong we say to the TI firm a friendly "FU".



The second option is worse, because we have to believe that the device operates in accordance with the time frame and, as it were, in accordance with the description, if you can call it that, and to write one byte to the output port, we have to send two, and the second will be used as an end marker transfer. The only explanation for such an elegant solution may be the desire to ensure compatibility with the above-mentioned 16-bit device, but, as they say, “having said A, the remaining letters of the alphabet must be spoken,” there is also a 24-bit version and 104-bit and devices with internal registers, let's make a single protocol for all occasions and for recording one byte we will transfer 20 pieces, and preferably 25, with 24 of them being empty and designed for compatibility with future versions, why stop there. At the same time, the postulate about the krivorosity of technical writers is still valid, since the descriptions of the functioning on 8 and 16 bit versions obviously diverge, and by 16 it is much more sane, though not perfect, but by 8 is just awful.



Than this option is worse than the first one, besides the fact that the developers made a very non-optimal solution for dubious benefits (that is, I wouldn’t accept such a decision, but I guess I don’t know everything) - because then there are two devices from different companies with the same designation, the same purpose, the same layout of the legs and at the same time they function according to different algorithms. And I did not know that it was possible. Purely theoretically, you can write an algorithm that will function correctly on both versions of the devices, leaving it as an exercise for an inquisitive reader, but a crutch, even as strong as you like, will never replace a living leg. My recommendations in this case are simply to forget about the existence of instruments from TI and use the correct devices and the correct description, by the way, assuming that only NXP is traded on Ali, this recommendation is somewhat delayed.



Now that the documentation from TI "was already indistinguishably mixed with food for sparrows on the first page and was already forgotten, because the academic's awakened thought might be interested in not with this insignificant object," we can try to analyze the library itself, we can try to understand in order to speed up the operation. To begin with, we define the main direction of optimization - since at any speed that 100, 400, 640, 800, 1000 kHz, we need at least 9 bit intervals to transmit a data byte, then the transmission time is crucial for the operation time of the function as a whole . Even with an interface frequency of 1 MHz, during the transmission of one byte send, 8 * 9 = 72 processor commands can be executed at a frequency of 8 MHz, therefore practically any complication of the program, resulting in a decrease in the number of bytes transmitted via the interface, will be fully justified. There is one consideration that clarifies a similar position, but more on that later.



We open the source code, we make our way through a lot of shell functions (it seems that the salary of programmers depends on the number of function signatures, neg?). For example, the public function init calls the private function init_private (and does nothing more), and that in turn calls the public method begin — not that I understand why they do it, but I guess I don’t know everything. Data is written by the write function, and commands are written by the command, which are wrappers for the send method, which calls the write4bits function, which calls expanderWrite and pulseEnable, which uses expanderWrite, which calls printIIc, which is a substitution for the write method of the TwoWire class to work with the interface itself whose source code lies (this is an obvious solution, isn't it) in the Wire file. We carefully consider the expanderWrite function and find exactly what we expected - each data byte is transmitted accompanied by its own start-bit, addressing command and stop-bit, that is, 8 + 9 bits of information are used to transmit 8 bits of information. level, which is clearly not the optimal solution.



By the way, one consideration in the programming style is that when I mastered C, the fashion was what the old style is now called (without function signatures), and this style grew out of Fortran, and in my opinion, this approach has an undoubted advantage, namely forced to arrange the functions in order of increasing complexity, since otherwise the code simply did not compile. And at the end of the file it was quite natural to find the main function, which made this approach logically complete. Therefore, when you looked at the implementation, it was natural to look for the code of the functions used in this one, above the text and at the very top were the basic functions (in this case, the output function), which determined the efficiency of the library. I do not urge to abandon the use of signatures in general, it is unlikely that such an appeal will have an effect, but even if there are signatures, no one forces you to have the functions implemented in an arbitrary order, so why do you do it badly when you can do it well and for free, and that's it ) and made in the library in question.



And one more interesting circumstance connected with function signatures in the Arduino environment. If you forget to write a function prototype, you risk seeing a very strange message from the compiler about an error in a line in which there is clearly no such error. The matter is that the environment requires the presence of prototypes of functions, and if you did not specify it, the preprocessor will not give you an error message (it would be too simple and it’s not Arduino style), it will form the signature itself, and arrange it at the very beginning of the program by shifting line numbering in error messages. And the error message is guaranteed to you if the function uses custom types, since the signature is located before their definition. Unusually convenient, isn't it? I remember the old joke "There are three ways to do something — the right, the wrong way, and the way of the navy."



Let us return to the transmission implementation - we already see a way to improve speed by 20/9 = 2 with a small amount of time due to the fact that every data byte will not be accompanied by an addressing byte, of course, this estimate will be from above and an accurate calculation will show 6 * 20 / (11 + 6 * 9) = 120/65 ~ 1.8 times, but this is only the beginning.



To continue, we will have to refer to the interface description connected to our device on the other hand and consider the interface with the screen. It can contain 4 or 8 data bits (4 in this case) and exchange tracking signals, of which the EN signal is important for us, which is an operation acknowledgment strobe. Since only 4 bits of data are used, the transfer of a byte of information would require the transfer of two nibbles, which could be eliminated by increasing the bit width, but not with this chip, since it would require at least 8 + 1 = 9 output ports, and we have only 8 , But more on that later. To take into account the need to form a strobe, in the library in question, data is first set and then the front and then the falling edge of the write pulse is formed with stable data, which requires the transfer of three bytes on the interface. Meanwhile, a careful reading of the documentation on the display interface shows that it requires stable data only on the leading front, so the formation of the falling front can be combined with the formation of the next piece of data, the only fact that should be borne in mind is that it would be good to reset strobe in a low state at the end of the session, although it is not necessary.



What we have as a result of the proposed, in my opinion, obvious changes - the required transmission time by one byte sent to the target device has decreased from 120 bit intervals to 1 + 9 + 4 * 9 + (+ 9) + 1 = 47 (56 in the case of strobe reset of the bit interval, the total performance increase is more than doubled with, I emphasize once again, quite obvious changes. — , , .



, , , , 100/120=0.83 (1.2 ), 9.600/11=0.87 16*2=32 . , 1.5 , ( 25%) . , .



, PulseEnable 1 50 . , , , , , 1+9=10 , , 10*1=10 1, . — 100 10*10=100, 400 , , , 2.5*10=25 , , 50 . , , 2*50=100 .



, — , 2 * 3 = 6 * (1+9+9+1) = 120 * 10/ = 1200 + 100 = 1300, 1500 , 2 * 2 = 4 * 9/ = 36+(1+9+1) = 47 * 10 / = 470, 2.6 .



(, , ), (, , , « — », , , ). ( , , , , « », ).



, , circuit.io, , , . , , , , . , , , , . , ( , ), .



( , ), — , , -, , 40 , 40%. .



, , , ATMega32, , TWI. , , , , , . , , 290 119 , — , . , , . , , 100 ( 4, ), , 100 ( 0.6, ). I2C ( , TWI ), , — , , , .



, , . , , — - .



— . , , . 40, , . , , , ?



, - . . , , , . , , . , , , .



: , , . , , ( , ) , . , , , , .



— . , , , . , .



— , . , — ( , — ) .



( ) , Uno Micro. , , , , , . (, ) . ( ) TWI , , .



, , , .



, — , . So:



— ) (, ),

— ) ( ),

— ) ,

— ) ,

— ) ,

— ) ,

...

— -) ,

) , .



, , « », , 20 , ?

Source: https://habr.com/ru/post/315586/



All Articles