├── .gitignore ├── LICENSE ├── README.md ├── SBUS_inverter.png ├── SPort_OSD.ino ├── charset.png ├── max7456.cpp ├── max7456.h └── max7456registers.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MinimOSD firmware using FrSky SPort telemetry as source 2 | ======================================================= 3 | 4 | This code allows you to use a MinimOSD to overlay FrSky SPort telemetry data on your FPV video feed. 5 | 6 | It uses the following libraries: 7 | * my FrSky SPort library for Arduino at https://github.com/zendes/SPort 8 | * a max7456 library from theboredengineers.com/2012/12/a-max7456-library-for-arduino/ 9 | 10 | To connect this to your Arduino, you'll need an inverter cable such as http://www.hobbyking.com/hobbyking/store/__24523__ZYX_S_S_BUS_Connection_Cable.html, or you can build your own using a TTL inverter or the schematic in the included SBUS_inverter.png file. 11 | 12 | Basic Installation 13 | ------------------ 14 | ``` 15 | $ cd 16 | $ git clone https://github.com/zendes/SPort_OSD.git 17 | $ cd libraries 18 | $ git clone https://github.com/zendes/SPort.git 19 | ``` 20 | 21 | Then restart your Arduino IDE and open SPort_OSD.ino -------------------------------------------------------------------------------- /SBUS_inverter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendes/SPort_OSD/a4f3512a0412543cbb4eb2974c7ecaabca6b25c6/SBUS_inverter.png -------------------------------------------------------------------------------- /SPort_OSD.ino: -------------------------------------------------------------------------------- 1 | #include 2 | SPort sport(Serial); 3 | 4 | #include 5 | #include "max7456.h" 6 | Max7456 osd; 7 | // Offset: 48,18 8 | // Dimensions: 0,0 to 25,12 9 | 10 | ISR(TIMER2_COMPA_vect) { 11 | sport.process(); 12 | } 13 | 14 | void setup() { 15 | sport.begin(); 16 | 17 | SPI.begin(); 18 | osd.init(10); 19 | osd.setDisplayOffsets(48,18); 20 | osd.activateOSD(); 21 | 22 | //consumption 23 | osd.print("0", 4, 10); 24 | osd.printMax7456Char(0x82, 6, 10); 25 | 26 | //current 27 | osd.print("0.00", 1, 11); 28 | osd.printMax7456Char(0x8F, 6, 11); 29 | 30 | //voltage 31 | osd.print("0.00", 1, 12); 32 | osd.printMax7456Char(0x8E, 6, 12); 33 | 34 | //velocity 35 | osd.print("0", 23, 10); 36 | osd.printMax7456Char(0x88, 25, 10); 37 | 38 | //altitude 39 | osd.print("0.0", 21, 11); 40 | osd.printMax7456Char(0x85, 25, 11); 41 | 42 | //time 43 | osd.print("00:00", 19, 12); 44 | osd.printMax7456Char(0xB3, 25, 12); 45 | } 46 | 47 | 48 | void loop() { 49 | //consumption 50 | if (sport.getVfasConsumption() < 10) { 51 | osd.print((int)sport.getVfasConsumption(), 4, 10, 1, 0); 52 | } else if (sport.getVfasConsumption() < 100) { 53 | osd.print((int)sport.getVfasConsumption(), 3, 10, 2, 0); 54 | } else if (sport.getVfasConsumption() < 1000) { 55 | osd.print((int)sport.getVfasConsumption(), 2, 10, 3, 0); 56 | } else { 57 | osd.print((int)sport.getVfasConsumption(), 1, 10, 4, 0); 58 | } 59 | 60 | //current 61 | if (sport.getVfasCurrent() < 10000) { 62 | osd.print(" ", 0, 11); 63 | osd.print((float)sport.getVfasCurrent() / 1000, 1, 11, 1, 2); 64 | } else { 65 | osd.print((float)sport.getVfasCurrent() / 1000, 0, 11, 2, 2); 66 | } 67 | 68 | //voltage 69 | if (sport.getVfasVoltage() < 10000) { 70 | osd.print(" ", 0, 12); 71 | osd.print((float)sport.getVfasVoltage() / 1000, 1, 12, 1, 2); 72 | } else { 73 | osd.print((float)sport.getVfasVoltage() / 1000, 0, 12, 2, 2); 74 | } 75 | 76 | //velocity 77 | 78 | //altitude 79 | osd.print(" ", 18, 11); 80 | if (sport.getVarioAltitude() < -1000) { 81 | osd.print((float)sport.getVarioAltitude() / 100, 19, 11, 2, 1); 82 | } else if (sport.getVarioAltitude() < 0) { 83 | osd.print((float)sport.getVarioAltitude() / 100, 20, 11, 1, 1); 84 | } else if (sport.getVarioAltitude() < 1000) { 85 | osd.print((float)sport.getVarioAltitude() / 100, 21, 11, 1, 1); 86 | } else if (sport.getVarioAltitude() < 10000) { 87 | osd.print((float)sport.getVarioAltitude() / 100, 20, 11, 2, 1); 88 | } else if (sport.getVarioAltitude() < 100000) { 89 | osd.print((float)sport.getVarioAltitude() / 100, 19, 11, 3, 1); 90 | } else { 91 | osd.print((float)sport.getVarioAltitude() / 100, 18, 11, 4, 1); 92 | } 93 | 94 | //time 95 | long counter = millis()/1000; 96 | osd.print(int(counter/60), 19, 12, 2, 0); 97 | osd.print(int(counter%60), 22, 12, 2, 0); 98 | 99 | delay(100); 100 | } 101 | -------------------------------------------------------------------------------- /charset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendes/SPort_OSD/a4f3512a0412543cbb4eb2974c7ecaabca6b25c6/charset.png -------------------------------------------------------------------------------- /max7456.cpp: -------------------------------------------------------------------------------- 1 | #include "max7456.h" 2 | #include 3 | #include 4 | 5 | 6 | //----------------------------------------------------------------------------- 7 | // Implements Max7456::Max7456 8 | //----------------------------------------------------------------------------- 9 | Max7456::Max7456(byte pinCS) 10 | { 11 | this->init(pinCS); 12 | } 13 | 14 | //----------------------------------------------------------------------------- 15 | // Implements Max7456::setBlinkParams 16 | //----------------------------------------------------------------------------- 17 | void Max7456::setBlinkParams(byte blinkBase, byte blinkDC) 18 | { 19 | _regVm1.bits.blinkingTime = blinkBase; 20 | _regVm1.bits.blinkingDutyCycle = blinkDC; 21 | digitalWrite(_pinCS, LOW); 22 | SPI.transfer(VM1_ADDRESS_WRITE); 23 | SPI.transfer(_regVm1.whole); 24 | digitalWrite(_pinCS, HIGH); 25 | } 26 | 27 | 28 | //----------------------------------------------------------------------------- 29 | // Implements Max7456::setDisplayOffsets 30 | //---------------------------------------------------------------------------- 31 | void Max7456::setDisplayOffsets(byte horizontal, byte vertical) 32 | { 33 | 34 | _regHos.whole = 0; 35 | _regVos.whole = 0; 36 | 37 | _regHos.bits.horizontalPositionOffset = horizontal; 38 | _regVos.bits.verticalPositionOffset = vertical; 39 | 40 | digitalWrite(_pinCS, LOW); 41 | SPI.transfer(HOS_ADDRESS_WRITE); 42 | SPI.transfer(_regHos.whole); 43 | 44 | SPI.transfer(VOS_ADDRESS_WRITE); 45 | SPI.transfer(_regVos.whole); 46 | 47 | digitalWrite(_pinCS, HIGH); 48 | } 49 | 50 | //----------------------------------------------------------------------------- 51 | // Implements Max7456::Max7456 52 | //----------------------------------------------------------------------------- 53 | Max7456::Max7456() 54 | { 55 | } 56 | 57 | 58 | //----------------------------------------------------------------------------- 59 | // Implements Max7456::sendCharacter 60 | //----------------------------------------------------------------------------- 61 | void Max7456::sendCharacter(const charact chara, byte x, byte y) 62 | { 63 | byte charAddress; 64 | if (y < 0) 65 | charAddress = x; 66 | else 67 | charAddress = x + (y << 4); 68 | activateOSD(false); 69 | //datasheet p38 70 | digitalWrite(_pinCS, LOW); 71 | SPI.transfer(CMAH_ADDRESS_WRITE); 72 | SPI.transfer(charAddress); 73 | 74 | for (byte i = 0 ; i < 54 ; i++) 75 | { 76 | SPI.transfer(CMAL_ADDRESS_WRITE); 77 | SPI.transfer(i); 78 | SPI.transfer(CMDI_ADDRESS_WRITE); 79 | SPI.transfer(chara[i]); 80 | } 81 | 82 | _regCmm = 0xA0; //To write the NVM array 83 | SPI.transfer(CMM_ADDRESS_WRITE); 84 | SPI.transfer(_regCmm); 85 | //while STAT[5] is not good, we wait. 86 | _regStat.bits.characterMemoryStatus = 1; 87 | while ( _regStat.bits.characterMemoryStatus == 1) 88 | { 89 | SPI.transfer(STAT_ADDRESS_READ); 90 | _regStat.whole = SPI.transfer(0x00); 91 | } 92 | 93 | 94 | digitalWrite(_pinCS, HIGH); 95 | } 96 | 97 | 98 | //----------------------------------------------------------------------------- 99 | // Implements Max7456::getCharacter 100 | //----------------------------------------------------------------------------- 101 | void Max7456::getCharacter(charact chara, byte x, byte y) 102 | { 103 | byte charAddress; 104 | 105 | 106 | if (y <= 0) 107 | charAddress = x; 108 | else 109 | charAddress = x + y * 16; 110 | 111 | activateOSD(false); 112 | //datasheet p38 113 | digitalWrite(_pinCS, LOW); 114 | 115 | 116 | SPI.transfer(CMAH_ADDRESS_WRITE); 117 | SPI.transfer(charAddress); 118 | 119 | _regCmm = 0x50; //To read from the NVM array 120 | SPI.transfer(CMM_ADDRESS_WRITE); 121 | SPI.transfer(_regCmm); 122 | 123 | 124 | for (byte i = 0 ; i < 54 ; i++) 125 | { 126 | SPI.transfer(CMAL_ADDRESS_WRITE); 127 | SPI.transfer(i); 128 | 129 | SPI.transfer(CMDO_ADDRESS_READ); //read from device through spi 130 | chara[i] = SPI.transfer(0x00); 131 | } 132 | 133 | digitalWrite(_pinCS, HIGH); 134 | 135 | } 136 | //----------------------------------------------------------------------------- 137 | // Implements Max7456::printCharacterToSerial 138 | //----------------------------------------------------------------------------- 139 | void Max7456::printCharacterToSerial(const charact array, bool img) 140 | { 141 | 142 | if (img) 143 | { 144 | CARACT car ; 145 | car = Max7456::byteArray2CARACT(array); 146 | 147 | Serial.println("------------"); 148 | for (int i = 0 ; i < 18 ; i++) 149 | { 150 | for (int j = 0 ; j < 3 ; j++) 151 | { 152 | printPixel(car.line[i].pixels[j].pix0); 153 | printPixel(car.line[i].pixels[j].pix1); 154 | printPixel(car.line[i].pixels[j].pix2); 155 | printPixel(car.line[i].pixels[j].pix3); 156 | } 157 | 158 | Serial.println(""); 159 | } 160 | Serial.println("------------"); 161 | } 162 | 163 | else 164 | { 165 | Serial.print("{"); 166 | for (unsigned int i = 0 ; i < 53 ; i++) 167 | { 168 | Serial.print("0x"); 169 | Serial.print(String(array[i], HEX)); 170 | Serial.print(", "); 171 | } 172 | Serial.print("0x"); 173 | Serial.print(String(array[53], HEX)); 174 | Serial.println("};"); 175 | } 176 | } 177 | 178 | void Max7456::printPixel(byte value) 179 | { 180 | switch (value ) 181 | { 182 | case COLOR_BLACK : 183 | Serial.print("#"); 184 | return; 185 | case COLOR_WHITE : 186 | Serial.print("*"); 187 | return; 188 | default: 189 | Serial.print(" "); 190 | return; 191 | } 192 | } 193 | 194 | 195 | //----------------------------------------------------------------------------- 196 | // Implements Max7456::print 197 | //----------------------------------------------------------------------------- 198 | void Max7456::print(const char string[], byte x, byte y, byte blink, byte inv) 199 | { 200 | char currentChar; 201 | byte size; 202 | byte *chars = NULL; 203 | 204 | if (!string) return; 205 | 206 | size = 0; 207 | currentChar = string[0]; 208 | 209 | while (currentChar != '\0') 210 | { 211 | currentChar = string[++size]; 212 | } 213 | 214 | chars = (byte*) malloc(size * sizeof(byte)); 215 | 216 | for (byte i = 0 ; i < size ; i++) 217 | { 218 | chars[i] = Max7456::giveMax7456CharFromAsciiChar(string[i]); 219 | } 220 | 221 | printMax7456Chars(chars, size, x, y, blink , inv ); 222 | free(chars); 223 | } 224 | 225 | 226 | void Max7456::printMax7456Char(const byte address, byte x, byte y, byte blink, byte inv) 227 | { 228 | byte ad = address; 229 | printMax7456Chars(&ad, 1, x, y, blink, inv); 230 | } 231 | 232 | //----------------------------------------------------------------------------- 233 | // Implements Max7456::printMax7456Chars 234 | //----------------------------------------------------------------------------- 235 | void Max7456::printMax7456Chars(byte chars[], byte size, byte x, byte y, byte blink , byte inv ) 236 | { 237 | byte currentCharMax7456; 238 | byte posAddressLO; 239 | byte posAddressHI; 240 | unsigned int posAddress; 241 | 242 | posAddress = 30 * y + x; 243 | 244 | posAddressHI = posAddress >> 8; 245 | posAddressLO = posAddress; 246 | 247 | _regDmm.whole = 0x01; 248 | 249 | _regDmm.bits.INV = inv; 250 | _regDmm.bits.BLK = blink; 251 | 252 | digitalWrite(_pinCS, LOW); 253 | SPI.transfer(DMM_ADDRESS_WRITE); 254 | 255 | 256 | 257 | SPI.transfer(_regDmm.whole); 258 | 259 | 260 | SPI.transfer(DMAH_ADDRESS_WRITE); // set start address high 261 | SPI.transfer(posAddressHI); 262 | 263 | SPI.transfer(DMAL_ADDRESS_WRITE); // set start address low 264 | SPI.transfer(posAddressLO); 265 | 266 | 267 | for (int i = 0; i < size ; i++) 268 | { 269 | currentCharMax7456 = chars[i]; 270 | SPI.transfer(DMDI_ADDRESS_WRITE); 271 | SPI.transfer(currentCharMax7456); 272 | 273 | } 274 | 275 | //end character (we're done). 276 | SPI.transfer(DMDI_ADDRESS_WRITE); 277 | SPI.transfer(0xff); 278 | 279 | /* 280 | _regVm0.bits. 281 | SPI.transfer(VM0_ADDRESS_WRITE); 282 | SPI.transfer(0x4c);*/ 283 | 284 | 285 | digitalWrite(_pinCS, HIGH); 286 | } 287 | 288 | 289 | //----------------------------------------------------------------------------- 290 | // Implements Max7456::print 291 | //----------------------------------------------------------------------------- 292 | 293 | void Max7456::print(double value, byte x, byte y, byte before, byte after, byte blink, byte inv) 294 | { 295 | char *strValue = NULL; 296 | 297 | strValue = (char*) malloc((before + after + 2) * sizeof(char)); 298 | 299 | 300 | if (after == 0) 301 | dtostrf(value, before + after, after, strValue); 302 | else 303 | dtostrf(value, before + after + 1, after, strValue); 304 | 305 | for (int i = 0 ; i < before + after + 1; i++) 306 | { 307 | if (strValue[i] == ' ' || strValue[i] == '-') 308 | strValue[i] = '0'; 309 | } 310 | if (value < 0) 311 | strValue[0] = '-'; 312 | if (after == 0) //If the result is bigger, we truncate it so the OSD won't be falsed. 313 | strValue[before] = '\0'; 314 | else 315 | strValue[before + after + 1] = '\0'; 316 | 317 | print(strValue, x, y, blink, inv); 318 | 319 | free(strValue); 320 | } 321 | 322 | 323 | //----------------------------------------------------------------------------- 324 | // Implements Max7456::giveMax7456CharFromAsciiChar 325 | //----------------------------------------------------------------------------- 326 | byte Max7456::giveMax7456CharFromAsciiChar(char ascii) 327 | { 328 | #ifdef MAX7456_TABLE_ASCII 329 | if (ascii >= ' ' && ascii <= 'z') 330 | return ascii - ' '; 331 | else 332 | return ascii; 333 | #else 334 | return ascii; 335 | #endif 336 | } 337 | 338 | 339 | //----------------------------------------------------------------------------- 340 | // Implements Max7456::clearScreen 341 | //----------------------------------------------------------------------------- 342 | void Max7456::clearScreen() 343 | { 344 | _regDmm.bits.clearDisplayMemory = 1 ; 345 | 346 | digitalWrite(_pinCS, LOW); 347 | 348 | SPI.transfer(DMM_ADDRESS_WRITE); 349 | SPI.transfer(_regDmm.whole); 350 | 351 | //wait for operation to be complete. 352 | while (_regDmm.bits.clearDisplayMemory == 1 ) 353 | { 354 | SPI.transfer(DMM_ADDRESS_READ); 355 | _regDmm.whole = SPI.transfer(0x00); 356 | } 357 | digitalWrite(_pinCS, HIGH); //disable device 358 | } 359 | 360 | 361 | //----------------------------------------------------------------------------- 362 | // Implements Max7456::init 363 | //----------------------------------------------------------------------------- 364 | void Max7456::init(byte iPinCS) 365 | { 366 | _pinCS = iPinCS; 367 | _isActivatedOsd = false; 368 | 369 | _regVm1.whole = 0b01000111; 370 | pinMode(iPinCS, OUTPUT); 371 | digitalWrite(iPinCS, HIGH); //disable device 372 | delay(100); //power up time 373 | 374 | digitalWrite(_pinCS, LOW); 375 | SPI.transfer(VM0_ADDRESS_WRITE); 376 | 377 | _regVm0.whole = 0x00; 378 | _regVm0.bits.videoSelect = 1; //PAL 379 | _regVm0.bits.softwareResetBit = 1; 380 | SPI.transfer(_regVm0.whole); 381 | digitalWrite(_pinCS, HIGH); 382 | delay(500); 383 | 384 | 385 | digitalWrite(_pinCS, LOW); 386 | for (int x = 0 ; x < 16 ; x++) 387 | { 388 | _regRb[x].whole = 0x00; 389 | _regRb[x].bits.characterWhiteLevel = 2; 390 | SPI.transfer(x + RB0_ADDRESS_WRITE); 391 | SPI.transfer(_regRb[x].whole); 392 | } 393 | 394 | _regVm0.whole = 0x00; 395 | 396 | _regVm0.bits.verticalSynch = 1; 397 | 398 | SPI.transfer(VM0_ADDRESS_WRITE); 399 | 400 | SPI.transfer(_regVm0.whole); 401 | 402 | 403 | // digitalWrite(_pinCS,HIGH); 404 | // 405 | // digitalWrite(_pinCS,LOW); 406 | //SPI.transfer(VM1_ADDRESS_WRITE); 407 | //SPI.transfer(0x0C); 408 | 409 | digitalWrite(_pinCS, HIGH); 410 | 411 | } 412 | 413 | 414 | //----------------------------------------------------------------------------- 415 | // Implements Max7456::activateOSD 416 | //----------------------------------------------------------------------------- 417 | void Max7456::activateOSD(bool act) 418 | { 419 | if (_isActivatedOsd != act) 420 | { 421 | 422 | _regVm0.bits.videoSelect = 1; 423 | if (act) 424 | _regVm0.bits.enableOSD = 1; 425 | else 426 | _regVm0.bits.enableOSD = 0; 427 | 428 | digitalWrite(_pinCS, LOW); 429 | SPI.transfer(VM0_ADDRESS_WRITE); 430 | SPI.transfer(_regVm0.whole); 431 | digitalWrite(_pinCS, HIGH); 432 | _isActivatedOsd = act; 433 | } 434 | } 435 | 436 | 437 | //----------------------------------------------------------------------------- 438 | // Implements Max7456::activateExternalVideo 439 | //----------------------------------------------------------------------------- 440 | void Max7456::activateExternalVideo(bool activExtVid) 441 | { 442 | if (!activExtVid) 443 | _regVm0.bits.synchSelect = 3; //11 444 | else 445 | _regVm0.bits.synchSelect = 0; //0 446 | 447 | digitalWrite(_pinCS, LOW); 448 | SPI.transfer(VM0_ADDRESS_WRITE); 449 | SPI.transfer(_regVm0.whole); 450 | digitalWrite(_pinCS, HIGH); 451 | } 452 | 453 | 454 | //----------------------------------------------------------------------------- 455 | // Implements Max7456::CARACT2ByteArray 456 | //----------------------------------------------------------------------------- 457 | byte* Max7456::CARACT2ByteArray(const CARACT car) 458 | { 459 | byte *array = NULL; 460 | array = new charact; 461 | for (int i = 0 ; i < 54 ; i++) 462 | array[i] = car.whole[i]; 463 | 464 | return array; 465 | } 466 | 467 | 468 | //----------------------------------------------------------------------------- 469 | // Implements Max7456::byteArray2CARACT 470 | //----------------------------------------------------------------------------- 471 | CARACT Max7456::byteArray2CARACT(const charact array) 472 | { 473 | CARACT car; 474 | for (int i = 0 ; i < 54 ; i++) 475 | car.whole[i] = array[i]; 476 | 477 | return car; 478 | } 479 | 480 | 481 | //----------------------------------------------------------------------------- 482 | // Implements Max7456::getCARACFromProgMem 483 | //----------------------------------------------------------------------------- 484 | void Max7456::getCARACFromProgMem(const prog_uchar *table, byte i, charact car) 485 | { 486 | unsigned long index; 487 | byte read; 488 | index = i * 54; 489 | for (unsigned long j = 0 ; j < 54 ; j++) 490 | { 491 | read = pgm_read_byte_near(table + index + j ); 492 | car[j] = read; 493 | if (car[j] == 0x55) 494 | car[j] = 0xff; 495 | } 496 | } 497 | 498 | 499 | -------------------------------------------------------------------------------- /max7456.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * max7456.h 4 | * 5 | * Created on: 10 oct. 2012 6 | * Author: Benoit 7 | */ 8 | 9 | #ifndef MAX7456_H 10 | #define MAX7456_H 11 | 12 | 13 | //def next only if you changed your table for an ascii one 14 | //i.e address 0x00 -> ' ' 15 | //.... 16 | // address 0x5A -> 'z' 17 | //#define MAX7456_TABLE_ASCII 18 | 19 | #include "max7456registers.h" 20 | 21 | 22 | 23 | /** 24 | * @mainpage Max7456 Arduino library 25 | */ 26 | 27 | /** 28 | * @example Max7456WriteTable.cpp 29 | */ 30 | 31 | 32 | /** 33 | * @class Max7456 34 | * @brief Represents a max7456 device communicating through SPI port 35 | */ 36 | class Max7456 37 | { 38 | public: 39 | 40 | 41 | /** 42 | * Default constructor 43 | */ 44 | Max7456(); 45 | 46 | 47 | /** 48 | * Constructor 49 | * Initialize communications and device 50 | * @param pinCS : pin ~CS of the arduino where max7456 is plugged. 51 | */ 52 | Max7456(byte pinCS); 53 | 54 | 55 | /** 56 | * Initialize communications and device 57 | * @param pinCS : pin ~CS of the arduino where max7456 is plugged. 58 | * @code 59 | * Max7456 osd; 60 | * osd.init(9); //Note it's that it's the same than usinge constructor Max7456(byte pinCS). 61 | * @endcode 62 | */ 63 | void init(byte pinCS); 64 | 65 | /** 66 | * Set the base time for blink. 67 | * @param blinkBase : the base time (see datasheet) 68 | * @param blinkDC : blink Duty cycle (see datasheet). 69 | */ 70 | void setBlinkParams(byte blinkBase, byte blinkDC); 71 | 72 | 73 | /** 74 | * Set Horizontal and Vertical display offset 75 | * @param horizontal : the horizontal offset in pixels (between 0 and 63). 76 | * @param vertical : the vertical offset in pixels (between 0 and 31). 77 | */ 78 | void setDisplayOffsets(byte horizontal, byte vertical); 79 | 80 | 81 | /** 82 | * Erase Display Memory. 83 | */ 84 | void clearScreen(); 85 | 86 | 87 | /** 88 | * Activate osd on screen 89 | * @param act : 90 | * @li if true OSD is activated 91 | * @li if false OSD is deactivated 92 | */ 93 | void activateOSD(bool act = true); 94 | 95 | 96 | /** 97 | * Activate input video as a background 98 | * @param activExtVid : 99 | * @li if true external video is displayed 100 | * @li if false external video is not displayed (bakground = grey) 101 | */ 102 | void activateExternalVideo(bool activExtVid = true); 103 | 104 | 105 | /** 106 | * Put a character in the memory character of max7456 107 | * @param array : the byte array representing the character (54 bytes long) 108 | * @param x : the horizontal position of character in memory 109 | * @param y : the vertical position of character in memory. 110 | * @code 111 | * charact c={0x44,....} //Whatever charact here 112 | * max.sendCharacter(c,4,5); //put c at 4th line 5th column ie. address 54. 113 | * max.sendCharacter(c,0x43); //put c in mem at address 43. 114 | * @endcode 115 | */ 116 | void sendCharacter(const charact array, byte x, byte y); 117 | 118 | 119 | /** 120 | * Get a character from the character memory of max7456 121 | * @param array : the byte array representing the character (54 bytes long) 122 | * @param x : the horizontal position of character in character memory 123 | * @param y : the vertical position of character in character memory 124 | */ 125 | void getCharacter(charact array, byte x, byte y); 126 | 127 | 128 | /** 129 | * Put a string in the display memory of max7456 130 | * @param string : The string to be displayed 131 | * @param x : the horizontal position of the string on screen 132 | * @param y : the vertical position of the string on screen 133 | * @param blink : if 1 then character will blink 134 | * @param inv : if 1 then color character will be inverted 135 | * @note : In order to have this function working, 136 | * you must rewrite your Max7456 Eeprom memory and make the first 137 | * characters the ascii characters between ' ' and 'z' 138 | * (' ' being at address 0x00, z being at address 'z'-' '). 139 | */ 140 | void print(const char string[], byte x, byte y, byte blink = 0, byte inv = 0); 141 | 142 | 143 | 144 | /** 145 | * Put a float in the display memory of max7456 146 | * @param value : The value to be displayed 147 | * @param x : the horizontal position of the value on screen 148 | * @param y : the vertical position of the value on screen 149 | * @param before : number of digits before comma 150 | * @param after : number of digits after comma 151 | * @param blink : if 1 then character will blink 152 | * @param inv : if 1 then color character will be inverted 153 | * @note The number of printed characters will be : before + after + 1. 154 | * @note Be aware of having a coherence between the number of digits you 155 | * enter in the function and the max. value of your double. If not may 156 | * result in unpredictable printed string. 157 | * @code 158 | * max.print(3.14,x,y,3,4); 159 | * //Will print "003.1400" on screen 160 | * @endcode 161 | */ 162 | void print(double value, byte x, byte y, byte before, byte after, byte blink = 0, byte inv = 0); 163 | 164 | 165 | /** 166 | * Put some characters in the display memory of max7456. 167 | * The characters are given by their address in the 168 | * character memory of the max7456. 169 | * @param chars : The characters address array to display 170 | * @param size : the array size 171 | * @param x : the horizontal position of the value on screen 172 | * @param y : the vertical position of the value on screen 173 | * @param blink : if 1 then character will blink 174 | * @param inv : if 1 then color character will be inverted 175 | * @code 176 | * char chars[0x04,0x45,0x54]; //the chars addresses array to be send to function. 177 | * max.printMax7456Chars(chars,3,x,y); 178 | * @endcode 179 | */ 180 | void printMax7456Chars(byte chars[], byte size, byte x, byte y, byte blink = 0, byte inv = 0); 181 | 182 | 183 | /** 184 | * Put one character from the character memory in the display memory of max7456 185 | * @param address : The address in character memory of the character to be displayed 186 | * @param x : the horizontal position of the string on screen 187 | * @param y : the vertical position of the string on screen 188 | * @param blink : if 1 then character will blink 189 | * @param inv : if 1 then color character will be inverted 190 | */ 191 | void printMax7456Char(const byte address, byte x, byte y, byte blink = 0, byte inv = 0); 192 | 193 | /** 194 | * Print a character to Serial port 195 | * @param array : the byte array representing the character (54 bytes long) 196 | * @param img : 197 | * @li true : the character will be displayed as a picture 198 | * @li false : the character will be displayed as a byte array 199 | */ 200 | static void printCharacterToSerial(const charact array, bool img = true); 201 | 202 | 203 | /** 204 | * Converts a CARACT character to a byte array representation. 205 | * @param car : the CARACT character 206 | * @return : the byte array representing the character (54 bytes long) 207 | */ 208 | static byte* CARACT2ByteArray(const CARACT car); 209 | 210 | 211 | /** 212 | * Converts a byte array to a CARACT character. 213 | * @param array : the byte array representing the character (54 bytes long) 214 | * @return : the CARACT character 215 | */ 216 | static CARACT byteArray2CARACT(const charact array); 217 | 218 | 219 | /** 220 | * Get the ith character from program memory 221 | * @param table the address of the array in prog memory 222 | * @param i the index of character. 223 | * @param c the returned character. 224 | * @note The table must be in program memory as an array of bytes (a multiple of 54). 225 | * @note When accessing this array, 0x55 are interpreted as 0xFF (you can't have 0xFF in program memory. 226 | * @note See file example for more informations. 227 | */ 228 | static void getCARACFromProgMem(const prog_uchar *table, byte i, charact c); 229 | 230 | private: 231 | 232 | byte giveMax7456CharFromAsciiChar(char ascii); 233 | static void printPixel(byte value); 234 | 235 | byte _pinCS; 236 | bool _isActivatedOsd; 237 | //registers (only here for convenience : not forced to be used). 238 | REG_VM0 _regVm0; 239 | REG_VM1 _regVm1; 240 | REG_HOS _regHos; 241 | REG_VOS _regVos; 242 | REG_DMM _regDmm; 243 | REG_DMAH _regDmah; // not used yet 244 | REG_DMAL _regDmal; // not used yet 245 | REG_DMDI _regDmdi; // not used yet 246 | REG_CMM _regCmm; 247 | REG_CMAH _regCmah; // not used yet 248 | REG_CMAL _regCmal; // not used yet 249 | REG_CMDI _regCmdi; // not used yet 250 | REG_OSDM _regOsdm; // not used yet 251 | REG_RBN _regRb[16]; // not used yet 252 | REG_OSDBL _regOsdbl; // not used yet 253 | REG_STAT _regStat; // not used yet 254 | DMDO _regDmdo; // not used yet 255 | REG_CMDO _regCmdo; // not used yet 256 | }; 257 | 258 | 259 | #endif /* MAX7456_H_ */ 260 | 261 | 262 | -------------------------------------------------------------------------------- /max7456registers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * max7456Registers.h 3 | * 4 | * Created on: 13 oct. 2012 5 | * Author: Benoit 6 | */ 7 | 8 | #ifndef MAX7456REGISTERS_H_ 9 | #define MAX7456REGISTERS_H_ 10 | 11 | 12 | #include 13 | 14 | 15 | /** 16 | * @typedef charact 17 | * @brief Represents a character as stored in max7456 character memory. 18 | */ 19 | typedef byte charact[54]; 20 | 21 | #define VM0_ADDRESS_WRITE 0x00 22 | #define VM0_ADDRESS_READ 0x80 23 | 24 | /** 25 | * @union REG_VM0 26 | * @brief Represents a Video Mode 0 Register value 27 | */ 28 | union REG_VM0 29 | { 30 | /**@brief The whole value*/ 31 | unsigned char whole ; 32 | /** 33 | * @var bits 34 | * @brief access to individual bits*/ 35 | struct 36 | { 37 | /**@brief Video BUffer Enable 38 | * @li 0 = Enable 39 | * @li 1 = Disable(VOUT is high impedance) 40 | */ 41 | unsigned char videoBuffer : 1; 42 | 43 | /**@brief Software Reset Bit 44 | * @li When bit set all register are set to default. 45 | */ 46 | unsigned char softwareResetBit : 1; 47 | 48 | /**@brief Vertical Synchronization of On-Screen Data 49 | * @li 0 = Enable osd immediately 50 | * @li 1 = Enable osd at the next ~VSYNC 51 | */ 52 | unsigned char verticalSynch : 1; 53 | 54 | /**@brief Enable Display of OSD Image 55 | * @li 0 = Off 56 | * @li 1 = On 57 | */ 58 | unsigned char enableOSD : 1; 59 | 60 | /**@brief Synch Select Mode 61 | * @li 0x (0 ou 1) = Autosynch select 62 | * @li 10 (2) = external 63 | * @li 11 (3) = internal 64 | */ 65 | unsigned char synchSelect : 2; 66 | 67 | /**@brief Video Standard Select 68 | * @li 0 = NTSC 69 | * @li 1 = PAL 70 | */ 71 | unsigned char videoSelect : 1; 72 | 73 | /**@brief don't care*/ 74 | unsigned char unused : 1; 75 | 76 | } bits; 77 | }; 78 | 79 | 80 | #define VM1_ADDRESS_WRITE 0x01 81 | #define VM1_ADDRESS_READ 0x81 82 | 83 | /**@union REG_VM1 84 | * @brief Represents a Video Mode 1 Register value. 85 | */ 86 | union REG_VM1 87 | { 88 | /**@brief The whole register value*/ 89 | unsigned char whole; 90 | /** 91 | * @var bits 92 | * @brief access to individual bits*/ 93 | struct 94 | { 95 | 96 | /**@brief Blinking Duty Cycle (On:Off) 97 | * @li b00 (0) = BT:BT 98 | * @li b01 (1) = BT:(2*BT) 99 | * @li b10 (2) = BT:(3*BT) 100 | * @li b11 (3) = (3*BT):BT 101 | */ 102 | unsigned char blinkingDutyCycle : 2; 103 | 104 | 105 | /**@brief Blinking Time (BT) 106 | * @li b00 (0) = 2 fields (NTSC = 33ms ; PAL = 40ms) 107 | * @li b01 (1) = 4 fields (NTSC = 67ms ; PAL = 80ms) 108 | * @li b10 (2) = 6 fields (NTSC = 100ms ; PAL = 120ms) 109 | * @li b11 (3) = 8 fields (NTSC = 133ms ; PAL = 160ms) 110 | */ 111 | unsigned char blinkingTime : 2; 112 | 113 | 114 | /**@brief Background Mode Brightness 115 | * @li b000 (0) = 0% 116 | * @li b001 (1) = 7% 117 | * @li b010 (2) = 14% 118 | * @li b011 (3) = 21% 119 | * @li b100 (4) = 28% 120 | * @li b101 (5) = 35% 121 | * @li b110 (6) = 43% 122 | * @li b111 (7) = 49% 123 | */ 124 | unsigned char backgroundModeBrightness : 3; 125 | 126 | /**@brief Background Mode 127 | * @li 0 = DMM[5] & DMM[7] sets the state of each character background 128 | * @li 1 = Sets all displayed background pixel to gray 129 | */ 130 | unsigned char backgroundMode : 1; 131 | } bits; 132 | }; 133 | 134 | #define HOS_ADDRESS_WRITE 0x02 135 | #define HOS_ADDRESS_READ 0x82 136 | 137 | /**@union REG_HOS 138 | * @brief Represents a Horizontal Offset Register value. 139 | */ 140 | union REG_HOS 141 | { 142 | /**@brief The whole register value*/ 143 | unsigned char whole; 144 | /** 145 | * @var bits 146 | * @brief access to individual bits*/ 147 | struct 148 | { 149 | /**@brief Vertical Position Offset 150 | * @li b00 0000 (0) = Farthest left (-32 pixels) 151 | * @li . 152 | * @li . 153 | * @li b10 0000 (32) = No horizontal offset 154 | * @li . 155 | * @li . 156 | * @li b11 1111 (31) = Farthest right (+31pixels) 157 | */ 158 | unsigned char horizontalPositionOffset : 6; 159 | 160 | /**@brief Don't care*/ 161 | unsigned char unsused : 2; 162 | 163 | } bits; 164 | }; 165 | 166 | 167 | #define VOS_ADDRESS_WRITE 0x03 168 | #define VOS_ADDRESS_READ 0x83 169 | 170 | /**@union REG_VOS 171 | * @brief Represents a Vertical Offset Register value. 172 | */ 173 | union REG_VOS 174 | { 175 | /**@brief The whole register value*/ 176 | unsigned char whole; 177 | /** 178 | * @var bits 179 | * @brief access to individual bits*/ 180 | struct 181 | { 182 | /**@brief Vertical Position Offset 183 | * @li b0 0000 (0) = Farthest up (+16 pixels) 184 | * @li . 185 | * @li . 186 | * @li b1 0000 (16) = No vertical offset 187 | * @li . 188 | * @li . 189 | * @li b1 1111 (31) = Farthest down (-15 pixels) 190 | */ 191 | unsigned char verticalPositionOffset : 5; 192 | /**@brief Don't care*/ 193 | unsigned char unsused : 3; 194 | 195 | } bits; 196 | }; 197 | 198 | #define DMM_ADDRESS_WRITE 0x04 199 | #define DMM_ADDRESS_READ 0x84 200 | /**@union REG_DMM 201 | * @brief Represents a Display Memory Mode value. 202 | */ 203 | union REG_DMM 204 | { 205 | /**@brief The whole register value*/ 206 | unsigned char whole; 207 | /** 208 | * @var bits 209 | * @brief access to individual bits*/ 210 | struct 211 | { 212 | /**@brief Auto-Increment Mode 213 | * @li 0 = Disabled 214 | * @li 1 = Enabled 215 | * @note When this bit is enabled for the first time, data in the Display Memory Address (DMAH[0] and 216 | DMAL[7:0]) registers are used as the starting location to which the data is written. When performing 217 | the auto-increment write for the display memory, the 8-bit address is internally generated, and 218 | therefore only 8-bit data is required by the SPI-compatible interface (Figure 21). The content is to 219 | be interpreted as a Character Address byte if DMAH[1] = 0 or a Character Attribute byte if 220 | DMAH[1] = 1. This mode is disabled by writing the escape character 1111 1111. 221 | If the Clear Display Memory bit is set, this bit is reset internally. 222 | */ 223 | unsigned char autoIncrementMode : 1; 224 | /**@brief Vertical Sync Clear (Valid only when clear display memory = 1, (DMM[2] = 1) ) 225 | * @li 0 = Immediately applies the clear display-memory command, DMM[2] = 1 226 | * @li 1 = Applies the clear display-memory command, DMM[2] = 1, at the next VSYNC time 227 | */ 228 | unsigned char verticalSynchClear : 1; 229 | /**@brief Clear Display Memory 230 | * @li 0 = Inactive 231 | * @li 1 = Clear (fill all display memories with zeros) 232 | * @note This bit is automatically cleared after the operation is completed (the operation requires 233 | * 20us). The user does not need to write a 0 afterwards. The status of the bit can be checked by 234 | * reading this register. 235 | * This operation is automatically performed: 236 | * a) On power-up 237 | * b) Immediately following the rising edge of RESET 238 | * c) Immediately following the rising edge of CS after VM0[1] has been set to 1 239 | */ 240 | unsigned char clearDisplayMemory : 1; 241 | /**@brief Invert Bit (applies to characters written in 16-bit operating mode) 242 | * @li 0 = Normal (white pixels display white, black pixels display black) 243 | * @li 1 = Invert (white pixels display black, black pixels display white) 244 | */ 245 | unsigned char INV : 1; 246 | /**@brief Blink Bit (applies to characters written in 16-bit operating mode) 247 | * @li 0 = Blinking off 248 | * @li 1 = Blinking on 249 | * @note Blinking rate and blinking duty cycle data in the Video Mode 1 (VM1) register are used for blinking control 250 | */ 251 | unsigned char BLK : 1; 252 | /**@brief Local Background Control Bit (applies to characters written in 16-bit operating mode) 253 | * @li 0 = sets the background pixels of the character to the video input (VIN) when in external sync mode. 254 | * @li 1 = sets the background pixels of the character to the background mode brightness level defined by VM1[6:4] in external or internal sync mode. 255 | * @note In internal sync mode, the local background control bit behaves as if it is set to 1 256 | */ 257 | unsigned char LBC : 1; 258 | /**@brief Operation Mode Selection 259 | * @li 0 = 16-bit operation mode 260 | * @li 1 = 8-bit operation mode 261 | */ 262 | unsigned char operationModeSelection : 1; 263 | 264 | /**@brief Don't care*/ 265 | unsigned char unsused : 1; 266 | 267 | 268 | 269 | } bits; 270 | }; 271 | 272 | 273 | #define DMAH_ADDRESS_WRITE 0x05 274 | #define DMAH_ADDRESS_READ 0x85 275 | /**@union REG_DMAH 276 | * @brief Represents a Display Memory Address High Register value 277 | */ 278 | union REG_DMAH 279 | { 280 | /**@brief The whole register value*/ 281 | unsigned char whole; 282 | /** 283 | * @var bits 284 | * @brief access to individual bits*/ 285 | struct 286 | { 287 | /**@brief 8th bit for Display Memory Address. 288 | */ 289 | unsigned char DisplayMemoryAdressBit8 : 1; 290 | unsigned char byteSelectionBit : 1; 291 | /**@brief Don't care*/ 292 | unsigned char unsused : 6; 293 | } bits; 294 | }; 295 | 296 | 297 | #define DMAL_ADDRESS_WRITE 0x06 298 | #define DMAL_ADDRESS_READ 0x86 299 | typedef unsigned char REG_DMAL; 300 | 301 | 302 | #define DMDI_ADDRESS_WRITE 0x07 303 | #define DMDI_ADDRESS_READ 0x87 304 | typedef unsigned char REG_DMDI; 305 | 306 | #define CMM_ADDRESS_WRITE 0x08 307 | #define CMM_ADDRESS_READ 0x88 308 | typedef unsigned char REG_CMM; 309 | 310 | #define CMAH_ADDRESS_WRITE 0x09 311 | #define CMAH_ADDRESS_READ 0x89 312 | 313 | /**@typedef REG_CMAH 314 | * @brief Represents a Character Memory Address HIGH value 315 | */ 316 | typedef unsigned char REG_CMAH; 317 | 318 | #define CMAL_ADDRESS_WRITE 0x0A 319 | #define CMAL_ADDRESS_READ 0x8A 320 | /**@typedef REG_CMAL 321 | * @brief Represents a Character Memory Address Low value 322 | */ 323 | typedef unsigned char REG_CMAL; 324 | 325 | #define CMDI_ADDRESS_WRITE 0x0B 326 | #define CMDI_ADDRESS_READ 0x8B 327 | 328 | /**@union REG_CMDI 329 | * @brief Represents a Character Memory Data In Register value 330 | */ 331 | union REG_CMDI 332 | { 333 | /**@brief The whole register value*/ 334 | unsigned char whole; 335 | /** 336 | * @var bits 337 | * @brief access to individual bits*/ 338 | struct 339 | { 340 | 341 | /**@brief value of the right most pixel*/ 342 | unsigned char rightMostPixel : 2; 343 | 344 | /**@brief value of the right center pixel*/ 345 | unsigned char rightCenterPixel : 2; 346 | 347 | /**@brief value of the left center pixel*/ 348 | unsigned char leftCenterPixel : 2; 349 | 350 | /**@brief value of the left most pixel*/ 351 | unsigned char leftMostPixel : 2; 352 | 353 | } bits; 354 | }; 355 | 356 | 357 | #define OSDM_ADDRESS_WRITE 0x0C 358 | #define OSDM_ADDRESS_READ 0x8C 359 | 360 | /**@union REG_OSDM 361 | * @brief Represents an OSD Insersion Mux Register value 362 | */ 363 | union REG_OSDM 364 | { 365 | /**@brief The whole register value*/ 366 | unsigned char whole; 367 | /** 368 | * @var bits 369 | * @brief access to individual bits 370 | * */ 371 | struct 372 | { 373 | /**@brief OSD Insersion Mux Switching Time 374 | * @li b000 (0) : 30ns (maximum sharpness/maximum crosscolor artifacts ) 375 | * @li b001 (1) : 35ns 376 | * @li b010 (2) : 50ns 377 | * @li b011 (3) : 75ns 378 | * @li b100 (4) : 100ns 379 | * @li b101 (5) : 120ns (minimum sharpness/minimum crosscolor artifacts) 380 | */ 381 | unsigned char osdInsertionMuxSwitchingTime : 3; 382 | 383 | 384 | /**@brief OSD Rise And Fall Time 385 | * @li b000 (0) : 20ns (maximum sharpness/maximum crosscolor artifacts ) 386 | * @li b001 (1) : 30ns 387 | * @li b010 (2): 35ns 388 | * @li b011 (3) : 60ns 389 | * @li b100 (4) : 80ns 390 | * @li b101 (5) : 110ns (minimum sharpness/minimum crosscolor artifacts) 391 | */ 392 | unsigned char osdRiseAndFallTime : 3; 393 | 394 | 395 | /**@brief don't care*/ 396 | unsigned char unused : 2; 397 | 398 | } bits; 399 | }; 400 | 401 | 402 | #define RB0_ADDRESS_WRITE 0x10 403 | #define RB0_ADDRESS_READ 0x90 404 | 405 | #define RB1_ADDRESS_WRITE 0x11 406 | #define RB1_ADDRESS_READ 0x91 407 | 408 | #define RB2_ADDRESS_WRITE 0x12 409 | #define RB2_ADDRESS_READ 0x92 410 | 411 | #define RB3_ADDRESS_WRITE 0x13 412 | #define RB3_ADDRESS_READ 0x93 413 | 414 | #define RB4_ADDRESS_WRITE 0x14 415 | #define RB4_ADDRESS_READ 0x94 416 | 417 | #define RB5_ADDRESS_WRITE 0x15 418 | #define RB5_ADDRESS_READ 0x95 419 | 420 | #define RB6_ADDRESS_WRITE 0x16 421 | #define RB6_ADDRESS_READ 0x96 422 | 423 | #define RB7_ADDRESS_WRITE 0x17 424 | #define RB7_ADDRESS_READ 0x97 425 | 426 | #define RB8_ADDRESS_WRITE 0x18 427 | #define RB8_ADDRESS_READ 0x98 428 | 429 | #define RB9_ADDRESS_WRITE 0x19 430 | #define RB9_ADDRESS_READ 0x99 431 | 432 | #define RBA_ADDRESS_WRITE 0x1A 433 | #define RBA_ADDRESS_READ 0x9A 434 | 435 | #define RBB_ADDRESS_WRITE 0x1B 436 | #define RBB_ADDRESS_READ 0x9B 437 | 438 | #define RBC_ADDRESS_WRITE 0x1C 439 | #define RBC_ADDRESS_READ 0x9C 440 | 441 | #define RBD_ADDRESS_WRITE 0x1D 442 | #define RBD_ADDRESS_READ 0x9D 443 | 444 | #define RBE_ADDRESS_WRITE 0x1E 445 | #define RBE_ADDRESS_READ 0x9E 446 | 447 | #define RBF_ADDRESS_WRITE 0x1F 448 | #define RBF_ADDRESS_READ 0x9F 449 | 450 | /**@union REG_RBN 451 | * @brief Represents a Row Brithness Register value (15 of them) 452 | */ 453 | union REG_RBN 454 | { 455 | /**@brief The whole register value*/ 456 | unsigned char whole; 457 | /** 458 | * @var bits 459 | * @brief access to individual bits*/ 460 | struct 461 | { 462 | /**@brief Character white level 463 | * @li b00 (0) = 120% 464 | * @li b01 (1) = 100% 465 | * @li b10 (2) = 90% 466 | * @li b11 (3) = 80% 467 | */ 468 | unsigned char characterWhiteLevel : 2; 469 | 470 | /**@brief Character black level 471 | * @li b00 (0) = 0% 472 | * @li b01 (1) = 10% 473 | * @li b10 (2) = 20% 474 | * @li b11 (3) = 20% 475 | */ 476 | unsigned char characterBlackLevel : 2; 477 | 478 | /**@brief don't care*/ 479 | unsigned char unused : 4; 480 | } bits; 481 | }; 482 | 483 | #define OSDBL_ADDRESS_WRITE 0x6C 484 | #define OSDBL_ADDRESS_READ 0xEC 485 | 486 | /**@union REG_OSDBL 487 | * @brief Represents an OSD Black Level Register value 488 | */ 489 | union REG_OSDBL 490 | { 491 | /**@brief The whole register value*/ 492 | unsigned char whole; 493 | /** 494 | * @var bits 495 | * @brief access to individual bits*/ 496 | struct 497 | { 498 | /**@brief do not change those bits : factory preset*/ 499 | unsigned char doNotChange : 4; 500 | /**@brief OSD Image Black Level Control. 501 | * @li 0 = automatic. 502 | * @li 1 = manual. 503 | */ 504 | unsigned char osdImageBlackLevelControl : 1; 505 | 506 | /**@brief don't care*/ 507 | unsigned char unused : 3; 508 | } bits; 509 | }; 510 | 511 | #define STAT_ADDRESS_READ 0xA0 //Read only 512 | 513 | /**@union REG_STAT 514 | * @brief Represents a Status Register value 515 | */ 516 | union REG_STAT 517 | { 518 | /**@brief The whole register value*/ 519 | unsigned char whole; 520 | /** 521 | * @var bits 522 | * @brief access to individual bits*/ 523 | struct 524 | { 525 | /**@brief Detected PAL. 526 | * @li 0 = PAL signal is not detected ad VIN. 527 | * @li 1 = PAL signal is detected at VIN. 528 | */ 529 | unsigned char PALDetected : 1; 530 | /**@brief Detected NTSC. 531 | * @li 0 = NTSC signal is not detected ad VIN. 532 | * @li 1 = NTSC signal is detected at VIN. 533 | */ 534 | unsigned char NTSCDetected : 1; 535 | /**@brief Loos-Of-Sync. 536 | * @li 0 = Sunc Active. Asserted after 32 consecutive input video lines. 537 | * @li 1 = No Sync. Asserted after 32 consecutive missing input video lines. 538 | */ 539 | unsigned char LOS : 1; 540 | /**@brief ~HSYNC Ouput Level. 541 | * @li 0 = Active during horizontal synch time. 542 | * @li 1 = inactive otherwise. 543 | */ 544 | unsigned char NOTHsynchOutputLevel : 1; 545 | /**@brief ~VSYNC Ouput Level. 546 | * @li 0 = Active during vertical synch time. 547 | * @li 1 = inactive otherwise. 548 | */ 549 | unsigned char NOTVsynchOutputLevel : 1; 550 | /**@brief Character Memory Status. 551 | * @li 0 = Available access. 552 | * @li 1 = Unavailable access. 553 | */ 554 | unsigned char characterMemoryStatus : 1; 555 | /**@brief Reset Mode. 556 | * @li 0 = Clear when power up reset mode is complete. 557 | * @li 1 = Set when in power-up reset mode. 558 | */ 559 | unsigned char resetMode : 1; 560 | /**@brief don't care.*/ 561 | unsigned char unused : 1; 562 | } bits; 563 | }; 564 | 565 | 566 | #define DMDO_ADDRESS_READ 0xB0 567 | 568 | /**@typedef DMDO 569 | * @brief represents a Display Memory Data Out Register value. 570 | */ 571 | typedef unsigned char DMDO; 572 | 573 | #define CMDO_ADDRESS_READ 0xC0 574 | 575 | /**@union REG_CMDO 576 | * @brief Represents a Character Memory Data Out value. 577 | */ 578 | union REG_CMDO 579 | { 580 | /**@brief The whole register value*/ 581 | unsigned char whole; 582 | /** 583 | * @var bits 584 | * @brief access to individual bits*/ 585 | struct 586 | { 587 | /**@brief right most pixel*/ 588 | unsigned char rightMostPowel : 2; 589 | /**@brief right center pixel*/ 590 | unsigned char rightCenterPixel : 2; 591 | /**@brief left center pixel*/ 592 | unsigned char leftCenterPixel : 2; 593 | /**@brief left most pixel*/ 594 | unsigned char leftMostPixel : 2; 595 | } bits; 596 | }; 597 | 598 | 599 | 600 | 601 | /**\def COLOR_BLACK 602 | * \brief Black value for a pixel (2bits) 603 | */ 604 | #define COLOR_BLACK 0 605 | 606 | 607 | /**\def COLOR_WHITE 608 | * \brief White value for a pixel (2bits) 609 | */ 610 | #define COLOR_WHITE 2 611 | 612 | 613 | /**\def COLOR_TRANSPARENT 614 | * \brief Transparent value for a pixel (2bits) 615 | */ 616 | #define COLOR_TRANSPARENT 1 617 | 618 | 619 | /**\def COLOR_GREY 620 | * \brief Grey value for a pixel (2bits) 621 | */ 622 | #define COLOR_GREY COLOR_TRANSPARENT 623 | 624 | 625 | /**@struct PIXEL 626 | * @brief represent a 4-pixels value 627 | */ 628 | struct PIXEL 629 | { 630 | /**@brief 4th pixel*/ 631 | byte pix3 : 2; 632 | /**@brief 3rd pixel*/ 633 | byte pix2 : 2; 634 | /**@brief 2nd pixel*/ 635 | byte pix1 : 2; 636 | 637 | 638 | /**@brief 1st pixel*/ 639 | byte pix0 : 2; 640 | 641 | }; 642 | 643 | /**@union LINE 644 | * @brief Represents a line in a max7456 character ie. 12 pixels 645 | */ 646 | union LINE 647 | { 648 | /**@brief the whole line*/ 649 | byte whole[3]; 650 | /**@brief individual 4-pixels access*/ 651 | struct PIXEL pixels[3]; 652 | }; 653 | 654 | 655 | /** 656 | * @union CARACT 657 | * @brief Represents a character with lines and pixels. 658 | * example : myCarac.line[3].pixels[2].pix2 = COLOR_TRANSPARENT ; 659 | */ 660 | union CARACT 661 | { 662 | /**@brief the whole CARACT as in max7456 Character Memory*/ 663 | charact whole; 664 | /**@brief acces with lines*/ 665 | union LINE line[18]; 666 | }; 667 | 668 | 669 | enum { 670 | _BT_BT = 0, 671 | _BT_2BT, 672 | _BT_3BT, 673 | _3BT_BT 674 | }; 675 | 676 | enum { 677 | _2fields = 0, 678 | _4fields, 679 | _6fields, 680 | _8fields 681 | }; 682 | 683 | 684 | #endif /* MAX7456REGISTERS_H_ */ 685 | --------------------------------------------------------------------------------