main.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn 0 .text 00000fe0 00000000 00000000 000000b4 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 00000004 00800060 00000fe0 00001094 2**0 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000016 00800064 00800064 00001098 2**0 ALLOC 3 .eeprom 0000019a 00810000 00810000 00001098 2**0 CONTENTS, ALLOC, LOAD, DATA 4 .stab 0000240c 00000000 00000000 00001234 2**2 CONTENTS, READONLY, DEBUGGING 5 .stabstr 00001071 00000000 00000000 00003640 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00000000 <__vectors>: 0: 69 c0 rjmp .+210 ; 0xd4 <__ctors_end> 2: 83 c0 rjmp .+262 ; 0x10a <__bad_interrupt> 4: bd c2 rjmp .+1402 ; 0x580 <__vector_2> 6: 81 c0 rjmp .+258 ; 0x10a <__bad_interrupt> 8: 80 c0 rjmp .+256 ; 0x10a <__bad_interrupt> a: 7f c0 rjmp .+254 ; 0x10a <__bad_interrupt> c: 7e c0 rjmp .+252 ; 0x10a <__bad_interrupt> e: 7d c0 rjmp .+250 ; 0x10a <__bad_interrupt> 10: 7c c0 rjmp .+248 ; 0x10a <__bad_interrupt> 12: 7b c0 rjmp .+246 ; 0x10a <__bad_interrupt> 14: 7a c0 rjmp .+244 ; 0x10a <__bad_interrupt> 16: 79 c0 rjmp .+242 ; 0x10a <__bad_interrupt> 18: 78 c0 rjmp .+240 ; 0x10a <__bad_interrupt> 1a: 77 c0 rjmp .+238 ; 0x10a <__bad_interrupt> 1c: 76 c0 rjmp .+236 ; 0x10a <__bad_interrupt> 1e: 1f c2 rjmp .+1086 ; 0x45e 20: 23 c2 rjmp .+1094 ; 0x468 22: 27 c2 rjmp .+1102 ; 0x472 24: 2b c2 rjmp .+1110 ; 0x47c 26: 33 c2 rjmp .+1126 ; 0x48e 28: 32 c2 rjmp .+1124 ; 0x48e 2a: 31 c2 rjmp .+1122 ; 0x48e 2c: 30 c2 rjmp .+1120 ; 0x48e 2e: 2f c2 rjmp .+1118 ; 0x48e 30: 2e c2 rjmp .+1116 ; 0x48e 32: 2d c2 rjmp .+1114 ; 0x48e 34: 2c c2 rjmp .+1112 ; 0x48e 36: 2b c2 rjmp .+1110 ; 0x48e 38: 2a c2 rjmp .+1108 ; 0x48e 3a: 29 c2 rjmp .+1106 ; 0x48e 3c: 28 c2 rjmp .+1104 ; 0x48e 3e: fc c1 rjmp .+1016 ; 0x438 40: fd c1 rjmp .+1018 ; 0x43c 42: 25 c2 rjmp .+1098 ; 0x48e 44: 00 c2 rjmp .+1024 ; 0x446 46: 23 c2 rjmp .+1094 ; 0x48e 48: 08 c2 rjmp .+1040 ; 0x45a 4a: 21 c2 rjmp .+1090 ; 0x48e 4c: 20 c2 rjmp .+1088 ; 0x48e 4e: 1f c2 rjmp .+1086 ; 0x48e 50: 1e c2 rjmp .+1084 ; 0x48e 52: ff c1 rjmp .+1022 ; 0x452 54: f6 c1 rjmp .+1004 ; 0x442 56: 1b c2 rjmp .+1078 ; 0x48e 58: 17 c2 rjmp .+1070 ; 0x488 5a: 19 c2 rjmp .+1074 ; 0x48e 5c: 18 c2 rjmp .+1072 ; 0x48e 5e: 17 c2 rjmp .+1070 ; 0x48e 60: e9 c1 rjmp .+978 ; 0x434 62: f5 c1 rjmp .+1002 ; 0x44e 64: 14 c2 rjmp .+1064 ; 0x48e 66: 13 c2 rjmp .+1062 ; 0x48e 68: 12 c2 rjmp .+1060 ; 0x48e 6a: 11 c2 rjmp .+1058 ; 0x48e 6c: ee c1 rjmp .+988 ; 0x44a 6e: 0f c2 rjmp .+1054 ; 0x48e 70: f2 c1 rjmp .+996 ; 0x456 00000072 : 72: 52 00 R. 00000074 : 74: 56 30 2e 38 37 00 V0.87. 0000007a : 7a: 23 00 #. 0000007c : 7c: 37 33 00 73. 0000007f : 7f: fc 7c 3c 1c 0c 04 84 c4 e4 f4 60 88 a8 90 40 28 .|<.......`...@( 8f: d0 08 20 78 b0 48 e0 a0 f0 68 d8 50 10 c0 30 18 .. x.H...h.P..0. 9f: 70 98 b8 c8 32 56 94 e8 ce e2 aa 4a 13 7a b4 b6 p...2V.....J.z.. af: 86 6a 36 52 8c 16 54 8b 44 ac 14 58 .j6R..T.D..X 000000bb : bb: 3f 2e 2f 21 2c 3a 3b 7e 24 5e 28 29 2d 40 5f 7c ?./!,:;~$^()-@_| cb: 3d 23 2b 2a 25 26 3c 3e 00 =#+*%&<>. 000000d4 <__ctors_end>: d4: 11 24 eor r1, r1 d6: 1f be out 0x3f, r1 ; 63 d8: cf e5 ldi r28, 0x5F ; 95 da: d2 e0 ldi r29, 0x02 ; 2 dc: de bf out 0x3e, r29 ; 62 de: cd bf out 0x3d, r28 ; 61 000000e0 <__do_copy_data>: e0: 10 e0 ldi r17, 0x00 ; 0 e2: a0 e6 ldi r26, 0x60 ; 96 e4: b0 e0 ldi r27, 0x00 ; 0 e6: e0 ee ldi r30, 0xE0 ; 224 e8: ff e0 ldi r31, 0x0F ; 15 ea: 02 c0 rjmp .+4 ; 0xf0 <.do_copy_data_start> 000000ec <.do_copy_data_loop>: ec: 05 90 lpm r0, Z+ ee: 0d 92 st X+, r0 000000f0 <.do_copy_data_start>: f0: a4 36 cpi r26, 0x64 ; 100 f2: b1 07 cpc r27, r17 f4: d9 f7 brne .-10 ; 0xec <.do_copy_data_loop> 000000f6 <__do_clear_bss>: f6: 10 e0 ldi r17, 0x00 ; 0 f8: a4 e6 ldi r26, 0x64 ; 100 fa: b0 e0 ldi r27, 0x00 ; 0 fc: 01 c0 rjmp .+2 ; 0x100 <.do_clear_bss_start> 000000fe <.do_clear_bss_loop>: fe: 1d 92 st X+, r1 00000100 <.do_clear_bss_start>: 100: aa 37 cpi r26, 0x7A ; 122 102: b1 07 cpc r27, r17 104: e1 f7 brne .-8 ; 0xfe <.do_clear_bss_loop> 106: 2a d2 rcall .+1108 ; 0x55c
108: 69 c7 rjmp .+3794 ; 0xfdc <_exit> 0000010a <__bad_interrupt>: 10a: 7a cf rjmp .-268 ; 0x0 <__vectors> 0000010c : for this specific application. @param n a number between 2 and 255 @return a random number between 0 and n-1 */ { 10c: 48 2f mov r20, r24 static word lfsr = 0xACE1; byte random; lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u); 10e: 20 91 62 00 lds r18, 0x0062 112: 30 91 63 00 lds r19, 0x0063 116: c9 01 movw r24, r18 118: 81 70 andi r24, 0x01 ; 1 11a: 90 70 andi r25, 0x00 ; 0 11c: 90 95 com r25 11e: 81 95 neg r24 120: 9f 4f sbci r25, 0xFF ; 255 122: 80 70 andi r24, 0x00 ; 0 124: 94 7b andi r25, 0xB4 ; 180 126: 36 95 lsr r19 128: 27 95 ror r18 12a: 82 27 eor r24, r18 12c: 93 27 eor r25, r19 12e: 90 93 63 00 sts 0x0063, r25 132: 80 93 62 00 sts 0x0062, r24 random = lfsr >> 8; // Byte = upper byte of word 136: 89 2f mov r24, r25 138: 01 c0 rjmp .+2 ; 0x13c while (random >= n) random -= n; // Cheap modulo :-) 13a: 84 1b sub r24, r20 13c: 84 17 cp r24, r20 13e: e8 f7 brcc .-6 ; 0x13a return random; } 140: 90 e0 ldi r25, 0x00 ; 0 142: 08 95 ret 00000144 : This creates a random callsign with 2 letters + 1 digit + 2 letters @param call a pointer to a buffer of sufficient size to store the callsign */ { 144: ef 92 push r14 146: ff 92 push r15 148: 1f 93 push r17 14a: cf 93 push r28 14c: df 93 push r29 14e: 7c 01 movw r14, r24 150: ec 01 movw r28, r24 152: 10 e0 ldi r17, 0x00 ; 0 // Generate a random callsign 2 Char, 1 Digit, 2 Char for (i=0;i<5;i++) { if (i == 2) 154: 12 30 cpi r17, 0x02 ; 2 156: 31 f4 brne .+12 ; 0x164 call[i]=lfsr(10) + '0'; 158: 8a e0 ldi r24, 0x0A ; 10 15a: d8 df rcall .-80 ; 0x10c 15c: 80 5d subi r24, 0xD0 ; 208 15e: f7 01 movw r30, r14 160: 82 83 std Z+2, r24 ; 0x02 162: 04 c0 rjmp .+8 ; 0x16c else call[i]=lfsr(26) + 'A'; 164: 8a e1 ldi r24, 0x1A ; 26 166: d2 df rcall .-92 ; 0x10c 168: 8f 5b subi r24, 0xBF ; 191 16a: 88 83 st Y, r24 { byte i; // Generate a random callsign 2 Char, 1 Digit, 2 Char for (i=0;i<5;i++) 16c: 1f 5f subi r17, 0xFF ; 255 16e: 21 96 adiw r28, 0x01 ; 1 170: 15 30 cpi r17, 0x05 ; 5 172: 81 f7 brne .-32 ; 0x154 call[i]=lfsr(10) + '0'; else call[i]=lfsr(26) + 'A'; } } 174: df 91 pop r29 176: cf 91 pop r28 178: 1f 91 pop r17 17a: ff 90 pop r15 17c: ef 90 pop r14 17e: 08 95 ret 00000180 : @param mode RECORD (read and store the beacon interval) or PLAY (beacon) @see main */ { 180: 1f 93 push r17 182: cf 93 push r28 184: df 93 push r29 186: 18 2f mov r17, r24 static word interval = 65000; // A dummy value that can not be reached static word timer; char c; if (interval == 65000) // 188: 80 91 60 00 lds r24, 0x0060 18c: 90 91 61 00 lds r25, 0x0061 190: 88 5e subi r24, 0xE8 ; 232 192: 9d 4f sbci r25, 0xFD ; 253 194: 49 f4 brne .+18 ; 0x1a8 interval = yackuser(READ, 1, 0); 196: 81 e0 ldi r24, 0x01 ; 1 198: 61 e0 ldi r22, 0x01 ; 1 19a: 40 e0 ldi r20, 0x00 ; 0 19c: 50 e0 ldi r21, 0x00 ; 0 19e: 7f d4 rcall .+2302 ; 0xa9e 1a0: 90 93 61 00 sts 0x0061, r25 1a4: 80 93 60 00 sts 0x0060, r24 if (mode == RECORD) 1a8: 11 30 cpi r17, 0x01 ; 1 1aa: 09 f0 breq .+2 ; 0x1ae 1ac: 47 c0 rjmp .+142 ; 0x23c { interval = 0; // Reset previous settings 1ae: 10 92 61 00 sts 0x0061, r1 1b2: 10 92 60 00 sts 0x0060, r1 timer = YACKSECS(DEFTIMEOUT); 1b6: 88 ee ldi r24, 0xE8 ; 232 1b8: 93 e0 ldi r25, 0x03 ; 3 1ba: 90 93 65 00 sts 0x0065, r25 1be: 80 93 64 00 sts 0x0064, r24 yackchar('N'); 1c2: 8e e4 ldi r24, 0x4E ; 78 1c4: e5 d4 rcall .+2506 ; 0xb90 if (c>='0' && c<='9') { interval *= 10; interval += c - '0'; timer = YACKSECS(DEFTIMEOUT); 1c6: c8 ee ldi r28, 0xE8 ; 232 1c8: d3 e0 ldi r29, 0x03 ; 3 1ca: 1a c0 rjmp .+52 ; 0x200 yackchar('N'); while(--timer) { c=yackiambic(FALSE); 1cc: 80 e0 ldi r24, 0x00 ; 0 1ce: 51 d3 rcall .+1698 ; 0x872 1d0: 18 2f mov r17, r24 yackbeat(); 1d2: 23 d2 rcall .+1094 ; 0x61a if (c>='0' && c<='9') 1d4: 81 2f mov r24, r17 1d6: 80 53 subi r24, 0x30 ; 48 1d8: 8a 30 cpi r24, 0x0A ; 10 1da: 90 f4 brcc .+36 ; 0x200 { interval *= 10; 1dc: 80 91 60 00 lds r24, 0x0060 1e0: 90 91 61 00 lds r25, 0x0061 1e4: 6a e0 ldi r22, 0x0A ; 10 1e6: 70 e0 ldi r23, 0x00 ; 0 1e8: 89 d6 rcall .+3346 ; 0xefc <__mulhi3> interval += c - '0'; 1ea: c0 97 sbiw r24, 0x30 ; 48 1ec: 81 0f add r24, r17 1ee: 91 1d adc r25, r1 1f0: 90 93 61 00 sts 0x0061, r25 1f4: 80 93 60 00 sts 0x0060, r24 timer = YACKSECS(DEFTIMEOUT); 1f8: d0 93 65 00 sts 0x0065, r29 1fc: c0 93 64 00 sts 0x0064, r28 interval = 0; // Reset previous settings timer = YACKSECS(DEFTIMEOUT); yackchar('N'); while(--timer) 200: 80 91 64 00 lds r24, 0x0064 204: 90 91 65 00 lds r25, 0x0065 208: 01 97 sbiw r24, 0x01 ; 1 20a: 90 93 65 00 sts 0x0065, r25 20e: 80 93 64 00 sts 0x0064, r24 212: 89 2b or r24, r25 214: d9 f6 brne .-74 ; 0x1cc interval += c - '0'; timer = YACKSECS(DEFTIMEOUT); } } if (interval >= 0 && interval <= 9999) 216: 40 91 60 00 lds r20, 0x0060 21a: 50 91 61 00 lds r21, 0x0061 21e: 87 e2 ldi r24, 0x27 ; 39 220: 40 31 cpi r20, 0x10 ; 16 222: 58 07 cpc r21, r24 224: 48 f4 brcc .+18 ; 0x238 { yackuser(WRITE, 1, interval); // Record interval 226: 82 e0 ldi r24, 0x02 ; 2 228: 61 e0 ldi r22, 0x01 ; 1 22a: 39 d4 rcall .+2162 ; 0xa9e yacknumber(interval); // Playback number 22c: 80 91 60 00 lds r24, 0x0060 230: 90 91 61 00 lds r25, 0x0061 234: 9a d5 rcall .+2868 ; 0xd6a 236: 35 c0 rjmp .+106 ; 0x2a2 <__stack+0x43> } else { yackerror(); 238: b5 d2 rcall .+1386 ; 0x7a4 23a: 33 c0 rjmp .+102 ; 0x2a2 <__stack+0x43> } } if ((mode == PLAY) && interval) 23c: 12 30 cpi r17, 0x02 ; 2 23e: 89 f5 brne .+98 ; 0x2a2 <__stack+0x43> 240: 80 91 60 00 lds r24, 0x0060 244: 90 91 61 00 lds r25, 0x0061 248: 89 2b or r24, r25 24a: 59 f1 breq .+86 ; 0x2a2 <__stack+0x43> #ifdef POWERSAVE // If we execute this, the interval counter is positive which means we are waiting // for a message playback. In this case we must not allow the CPU to enter sleep mode. yackpower(FALSE); // Inhibit sleep mode 24c: 80 e0 ldi r24, 0x00 ; 0 24e: a2 d1 rcall .+836 ; 0x594 #endif if (timer) timer--; // Countdown until a second has expired 250: 80 91 64 00 lds r24, 0x0064 254: 90 91 65 00 lds r25, 0x0065 258: 00 97 sbiw r24, 0x00 ; 0 25a: 31 f0 breq .+12 ; 0x268 <__stack+0x9> 25c: 01 97 sbiw r24, 0x01 ; 1 25e: 90 93 65 00 sts 0x0065, r25 262: 80 93 64 00 sts 0x0064, r24 266: 1d c0 rjmp .+58 ; 0x2a2 <__stack+0x43> else { timer = YACKSECS(1); // Reset timer 268: 88 ec ldi r24, 0xC8 ; 200 26a: 90 e0 ldi r25, 0x00 ; 0 26c: 90 93 65 00 sts 0x0065, r25 270: 80 93 64 00 sts 0x0064, r24 if ((--interval)==0) // Interval was > 0. Did decrement bring it to 0? 274: 80 91 60 00 lds r24, 0x0060 278: 90 91 61 00 lds r25, 0x0061 27c: 01 97 sbiw r24, 0x01 ; 1 27e: 90 93 61 00 sts 0x0061, r25 282: 80 93 60 00 sts 0x0060, r24 286: 89 2b or r24, r25 288: 61 f4 brne .+24 ; 0x2a2 <__stack+0x43> { interval = yackuser(READ, 1, 0); // Reset the interval timer 28a: 81 e0 ldi r24, 0x01 ; 1 28c: 61 e0 ldi r22, 0x01 ; 1 28e: 40 e0 ldi r20, 0x00 ; 0 290: 50 e0 ldi r21, 0x00 ; 0 292: 05 d4 rcall .+2058 ; 0xa9e 294: 90 93 61 00 sts 0x0061, r25 298: 80 93 60 00 sts 0x0060, r24 yackmessage(PLAY,4); // And play message 4 29c: 82 e0 ldi r24, 0x02 ; 2 29e: 64 e0 ldi r22, 0x04 ; 4 2a0: be d4 rcall .+2428 ; 0xc1e } } } 2a2: df 91 pop r29 2a4: cf 91 pop r28 2a6: 1f 91 pop r17 2a8: 08 95 ret 000002aa : This implements callsign training. The keyer plays a random callsign and the user repeats it on the paddle. If a mistake happens, the error prosign is sounded, the callsign sent again and the user attempts one more time. */ { 2aa: af 92 push r10 2ac: bf 92 push r11 2ae: cf 92 push r12 2b0: df 92 push r13 2b2: ef 92 push r14 2b4: ff 92 push r15 2b6: 0f 93 push r16 2b8: 1f 93 push r17 2ba: df 93 push r29 2bc: cf 93 push r28 2be: 00 d0 rcall .+0 ; 0x2c0 2c0: 00 d0 rcall .+0 ; 0x2c2 2c2: 0f 92 push r0 2c4: cd b7 in r28, 0x3d ; 61 2c6: de b7 in r29, 0x3e ; 62 word timer; // Timeout timer while(1) // Endless loop will exit throught RETURN statement only { rndcall(call); // Make up a callsign 2c8: 6e 01 movw r12, r28 2ca: 08 94 sec 2cc: c1 1c adc r12, r1 2ce: d1 1c adc r13, r1 while(i<5) { if (!i) // If nothing guessed yet, play the callsign { yackdelay(2 * IWGLEN); // Give him some time to breathe b4 next callsign for (n=0;n<5;n++) 2d0: 66 e0 ldi r22, 0x06 ; 6 2d2: a6 2e mov r10, r22 2d4: b1 2c mov r11, r1 2d6: ac 0e add r10, r28 2d8: bd 1e adc r11, r29 word timer; // Timeout timer while(1) // Endless loop will exit throught RETURN statement only { rndcall(call); // Make up a callsign 2da: c6 01 movw r24, r12 2dc: 33 df rcall .-410 ; 0x144 2de: ff 24 eor r15, r15 i=0; // i counts the number of chracters correctly guessed while(i<5) { if (!i) // If nothing guessed yet, play the callsign 2e0: ff 20 and r15, r15 2e2: 81 f4 brne .+32 ; 0x304 { yackdelay(2 * IWGLEN); // Give him some time to breathe b4 next callsign 2e4: 8e e0 ldi r24, 0x0E ; 14 2e6: 2a d2 rcall .+1108 ; 0x73c 2e8: 86 01 movw r16, r12 for (n=0;n<5;n++) { yackchar(call[n]); 2ea: f8 01 movw r30, r16 2ec: 80 81 ld r24, Z 2ee: 50 d4 rcall .+2208 ; 0xb90 yackfarns(); // Add potential farnsworth delays 2f0: 38 d2 rcall .+1136 ; 0x762 if(yackctrlkey(TRUE)) 2f2: 81 e0 ldi r24, 0x01 ; 1 2f4: 18 d4 rcall .+2096 ; 0xb26 2f6: 88 23 and r24, r24 2f8: 71 f5 brne .+92 ; 0x356 return; // Abort if requested.. 2fa: 0f 5f subi r16, 0xFF ; 255 2fc: 1f 4f sbci r17, 0xFF ; 255 while(i<5) { if (!i) // If nothing guessed yet, play the callsign { yackdelay(2 * IWGLEN); // Give him some time to breathe b4 next callsign for (n=0;n<5;n++) 2fe: 0a 15 cp r16, r10 300: 1b 05 cpc r17, r11 302: 99 f7 brne .-26 ; 0x2ea 304: 00 ed ldi r16, 0xD0 ; 208 306: 17 e0 ldi r17, 0x07 ; 7 timer = YACKSECS(TRAINTIMEOUT); do { c=yackiambic(OFF); // Wait for a character 308: 80 e0 ldi r24, 0x00 ; 0 30a: b3 d2 rcall .+1382 ; 0x872 30c: e8 2e mov r14, r24 yackbeat(); // FSM heartbeat 30e: 85 d1 rcall .+778 ; 0x61a timer--; // Countdown 310: 01 50 subi r16, 0x01 ; 1 312: 10 40 sbci r17, 0x00 ; 0 } while ((!c) && timer && !(yackctrlkey(FALSE))); // Stop when character or timeout 314: ee 20 and r14, r14 316: 41 f4 brne .+16 ; 0x328 318: 01 15 cp r16, r1 31a: 11 05 cpc r17, r1 31c: e1 f0 breq .+56 ; 0x356 31e: 80 e0 ldi r24, 0x00 ; 0 320: 02 d4 rcall .+2052 ; 0xb26 322: 88 23 and r24, r24 324: 89 f3 breq .-30 ; 0x308 326: 02 c0 rjmp .+4 ; 0x32c if (timer == 0 || yackctrlkey(TRUE)) // If termination because of timeout 328: 01 2b or r16, r17 32a: a9 f0 breq .+42 ; 0x356 32c: 81 e0 ldi r24, 0x01 ; 1 32e: fb d3 rcall .+2038 ; 0xb26 330: 88 23 and r24, r24 332: 89 f4 brne .+34 ; 0x356 return; // then return if (call[i] == c) // Was it the right character? 334: f6 01 movw r30, r12 336: ef 0d add r30, r15 338: f1 1d adc r31, r1 33a: 80 81 ld r24, Z 33c: 8e 15 cp r24, r14 33e: 29 f4 brne .+10 ; 0x34a i++; // then increment counter 340: f3 94 inc r15 { rndcall(call); // Make up a callsign i=0; // i counts the number of chracters correctly guessed while(i<5) 342: f4 e0 ldi r31, 0x04 ; 4 344: ff 15 cp r31, r15 346: 60 f6 brcc .-104 ; 0x2e0 348: 03 c0 rjmp .+6 ; 0x350 if (call[i] == c) // Was it the right character? i++; // then increment counter else { yackerror(); // Send an error prosign 34a: 2c d2 rcall .+1112 ; 0x7a4 34c: ff 24 eor r15, r15 34e: ca cf rjmp .-108 ; 0x2e4 i=0; // And reset the counter } } yackchar ('R'); 350: 82 e5 ldi r24, 0x52 ; 82 352: 1e d4 rcall .+2108 ; 0xb90 354: c2 cf rjmp .-124 ; 0x2da } } 356: 0f 90 pop r0 358: 0f 90 pop r0 35a: 0f 90 pop r0 35c: 0f 90 pop r0 35e: 0f 90 pop r0 360: cf 91 pop r28 362: df 91 pop r29 364: 1f 91 pop r17 366: 0f 91 pop r16 368: ff 90 pop r15 36a: ef 90 pop r14 36c: df 90 pop r13 36e: cf 90 pop r12 370: bf 90 pop r11 372: af 90 pop r10 374: 08 95 ret 00000376 : This function implements farnsworth pause change mode. Farnsworth pauses can be added or removed with the paddle keys. */ { 376: 1f 93 push r17 378: 10 e0 ldi r17, 0x00 ; 0 byte timer=0; while (timer++ != FARNSREPEAT) // while not yet timed out { if (yackctrlkey(TRUE)) {return;} 37a: 81 e0 ldi r24, 0x01 ; 1 37c: d4 d3 rcall .+1960 ; 0xb26 37e: 88 23 and r24, r24 380: b9 f4 brne .+46 ; 0x3b0 yackplay(DIT); 382: 81 e0 ldi r24, 0x01 ; 1 384: fd d1 rcall .+1018 ; 0x780 yackdelay(IEGLEN); // Inter Element gap 386: 81 e0 ldi r24, 0x01 ; 1 388: d9 d1 rcall .+946 ; 0x73c yackplay(DAH); 38a: 82 e0 ldi r24, 0x02 ; 2 38c: f9 d1 rcall .+1010 ; 0x780 yackdelay(ICGLEN); // Inter Character gap 38e: 83 e0 ldi r24, 0x03 ; 3 390: d5 d1 rcall .+938 ; 0x73c yackfarns(); // Additional Farnsworth delay 392: e7 d1 rcall .+974 ; 0x762 if(!(KEYINP & (1< { yackspeed(DOWN,FARNSWORTH); // increase interword spacing 398: 82 e0 ldi r24, 0x02 ; 2 39a: 07 c0 rjmp .+14 ; 0x3aa timer=0; } else if(!(KEYINP & (1< */ { byte timer=0; while (timer++ != FARNSREPEAT) // while not yet timed out 3a0: 1f 5f subi r17, 0xFF ; 255 3a2: 1a 30 cpi r17, 0x0A ; 10 3a4: 51 f7 brne .-44 ; 0x37a 3a6: 04 c0 rjmp .+8 ; 0x3b0 timer=0; } else if(!(KEYINP & (1< 3ae: e4 cf rjmp .-56 ; 0x378 } } } 3b0: 1f 91 pop r17 3b2: 08 95 ret 000003b4 : This function implements pitch change mode. A series of dots is played and pitch can be adjusted using the paddle levers. Once 10 dots have been played at the same pitch, the mode terminates */ { 3b4: cf 93 push r28 3b6: df 93 push r29 3b8: ca e0 ldi r28, 0x0A ; 10 3ba: d0 e0 ldi r29, 0x00 ; 0 word timer=PITCHREPEAT; while (timer) // while not yet timed out { timer--; yackchar('E'); // play an 'e' 3bc: 85 e4 ldi r24, 0x45 ; 69 3be: e8 d3 rcall .+2000 ; 0xb90 if (yackctrlkey(TRUE)) {return;} 3c0: 81 e0 ldi r24, 0x01 ; 1 3c2: b1 d3 rcall .+1890 ; 0xb26 3c4: 88 23 and r24, r24 3c6: 79 f4 brne .+30 ; 0x3e6 if(!(KEYINP & (1< { word timer=PITCHREPEAT; while (timer) // while not yet timed out { timer--; 3cc: 21 97 sbiw r28, 0x01 ; 1 3ce: 04 c0 rjmp .+8 ; 0x3d8 if (yackctrlkey(TRUE)) {return;} if(!(KEYINP & (1< 3d4: ca e0 ldi r28, 0x0A ; 10 3d6: d0 e0 ldi r29, 0x00 ; 0 timer=PITCHREPEAT; } if(!(KEYINP & (1< { yackpitch(UP); // lower the pitch 3dc: 81 e0 ldi r24, 0x01 ; 1 3de: 24 d1 rcall .+584 ; 0x628 3e0: eb cf rjmp .-42 ; 0x3b8 Once 10 dots have been played at the same pitch, the mode terminates */ { word timer=PITCHREPEAT; while (timer) // while not yet timed out 3e2: 20 97 sbiw r28, 0x00 ; 0 3e4: 59 f7 brne .-42 ; 0x3bc } } } 3e6: df 91 pop r29 3e8: cf 91 pop r28 3ea: 08 95 ret 000003ec : This routine implements command mode. Entries are read from the paddle and interpreted as commands. */ { 3ec: 1f 93 push r17 3ee: cf 93 push r28 3f0: df 93 push r29 char c; // Character from Morse key word timer; // Exit timer yackinhibit(ON); // Sidetone = on, Keyer = off 3f2: 81 e0 ldi r24, 0x01 ; 1 3f4: 90 d1 rcall .+800 ; 0x716 yackchar('?'); // Play Greeting 3f6: 8f e3 ldi r24, 0x3F ; 63 3f8: cb d3 rcall .+1942 ; 0xb90 3fa: c8 ee ldi r28, 0xE8 ; 232 3fc: d3 e0 ldi r29, 0x03 ; 3 3fe: 9e c0 rjmp .+316 ; 0x53c timer = YACKSECS(DEFTIMEOUT); // Time out after 10 seconds while ((yackctrlkey(TRUE)==0) && (timer-- > 0)) { c=yackiambic(OFF); 400: 80 e0 ldi r24, 0x00 ; 0 402: 37 d2 rcall .+1134 ; 0x872 404: 18 2f mov r17, r24 if (c) timer = YACKSECS(DEFTIMEOUT); // Reset timeout if character read 406: 88 23 and r24, r24 408: 19 f0 breq .+6 ; 0x410 40a: c8 ee ldi r28, 0xE8 ; 232 40c: d3 e0 ldi r29, 0x03 ; 3 40e: 01 c0 rjmp .+2 ; 0x412 yackchar('?'); // Play Greeting timer = YACKSECS(DEFTIMEOUT); // Time out after 10 seconds while ((yackctrlkey(TRUE)==0) && (timer-- > 0)) 410: 21 97 sbiw r28, 0x01 ; 1 { c=yackiambic(OFF); if (c) timer = YACKSECS(DEFTIMEOUT); // Reset timeout if character read yackbeat(); 412: 03 d1 rcall .+518 ; 0x61a lfsr(255); // Keep seeding the LFSR so we get different callsigns 414: 8f ef ldi r24, 0xFF ; 255 416: 7a de rcall .-780 ; 0x10c if (!yackflag(CONFLOCK)) // No Configuration lock? 418: 82 e0 ldi r24, 0x02 ; 2 41a: 44 d1 rcall .+648 ; 0x6a4 41c: 88 23 and r24, r24 41e: b9 f5 brne .+110 ; 0x48e { switch (c) // These are the lockable configuration commands 420: 81 2f mov r24, r17 422: 90 e0 ldi r25, 0x00 ; 0 424: fc 01 movw r30, r24 426: f1 97 sbiw r30, 0x31 ; 49 428: ea 32 cpi r30, 0x2A ; 42 42a: f1 05 cpc r31, r1 42c: 80 f5 brcc .+96 ; 0x48e 42e: e1 5f subi r30, 0xF1 ; 241 430: ff 4f sbci r31, 0xFF ; 255 432: 09 94 ijmp { case 'R': // Reset yackreset(); 434: 0d d5 rcall .+2586 ; 0xe50 436: 79 c0 rjmp .+242 ; 0x52a c = TRUE; break; case 'A': // IAMBIC A yackmode(IAMBICA); 438: 80 e0 ldi r24, 0x00 ; 0 43a: 01 c0 rjmp .+2 ; 0x43e c = TRUE; break; case 'B': // IAMBIC B yackmode(IAMBICB); 43c: 84 e0 ldi r24, 0x04 ; 4 43e: 26 d1 rcall .+588 ; 0x68c 440: 74 c0 rjmp .+232 ; 0x52a c = TRUE; break; case 'L': // ULTIMATIC yackmode(ULTIMATIC); 442: 88 e0 ldi r24, 0x08 ; 8 444: fc cf rjmp .-8 ; 0x43e c = TRUE; break; case 'D': // DAHPRIO yackmode(DAHPRIO); 446: 8c e0 ldi r24, 0x0C ; 12 448: fa cf rjmp .-12 ; 0x43e c = TRUE; break; case 'X': // Paddle swapping yacktoggle(PDLSWAP); 44a: 80 e8 ldi r24, 0x80 ; 128 44c: 4e c0 rjmp .+156 ; 0x4ea c = TRUE; break; case 'S': // Sidetone toggle yacktoggle(SIDETONE); 44e: 80 e1 ldi r24, 0x10 ; 16 450: 4c c0 rjmp .+152 ; 0x4ea c = TRUE; break; case 'K': // TX keying toggle yacktoggle(TXKEY); 452: 80 e2 ldi r24, 0x20 ; 32 454: 4a c0 rjmp .+148 ; 0x4ea c = TRUE; break; case 'Z': // Farnsworth pause setfarns(); 456: 8f df rcall .-226 ; 0x376 458: 68 c0 rjmp .+208 ; 0x52a c = TRUE; break; case 'F': // TX level inverter toggle yacktoggle(TXINV); 45a: 80 e4 ldi r24, 0x40 ; 64 45c: 46 c0 rjmp .+140 ; 0x4ea c = TRUE; break; case '1': // Record Macro 1 yackchar('1'); 45e: 81 e3 ldi r24, 0x31 ; 49 460: 97 d3 rcall .+1838 ; 0xb90 yackmessage(RECORD,1); 462: 81 e0 ldi r24, 0x01 ; 1 464: 61 e0 ldi r22, 0x01 ; 1 466: 0e c0 rjmp .+28 ; 0x484 c = TRUE; break; case '2': // Record Macro 2 yackchar('2'); 468: 82 e3 ldi r24, 0x32 ; 50 46a: 92 d3 rcall .+1828 ; 0xb90 yackmessage(RECORD,2); 46c: 81 e0 ldi r24, 0x01 ; 1 46e: 62 e0 ldi r22, 0x02 ; 2 470: 09 c0 rjmp .+18 ; 0x484 c = TRUE; break; case '3': // Record Macro 3 yackchar('3'); 472: 83 e3 ldi r24, 0x33 ; 51 474: 8d d3 rcall .+1818 ; 0xb90 yackmessage(RECORD,3); 476: 81 e0 ldi r24, 0x01 ; 1 478: 63 e0 ldi r22, 0x03 ; 3 47a: 04 c0 rjmp .+8 ; 0x484 c = TRUE; break; case '4': // Record Macro 4 yackchar('4'); 47c: 84 e3 ldi r24, 0x34 ; 52 47e: 88 d3 rcall .+1808 ; 0xb90 yackmessage(RECORD,4); 480: 81 e0 ldi r24, 0x01 ; 1 482: 64 e0 ldi r22, 0x04 ; 4 484: cc d3 rcall .+1944 ; 0xc1e 486: 51 c0 rjmp .+162 ; 0x52a c = TRUE; break; case 'N': // Automatic Beacon beacon(RECORD); 488: 81 e0 ldi r24, 0x01 ; 1 48a: 7a de rcall .-780 ; 0x180 48c: 4e c0 rjmp .+156 ; 0x52a } } switch (c) // Commands that can be used anytime 48e: 1d 34 cpi r17, 0x4D ; 77 490: e9 f1 breq .+122 ; 0x50c 492: 1e 34 cpi r17, 0x4E ; 78 494: 68 f4 brcc .+26 ; 0x4b0 496: 13 34 cpi r17, 0x43 ; 67 498: 29 f1 breq .+74 ; 0x4e4 49a: 14 34 cpi r17, 0x44 ; 68 49c: 20 f4 brcc .+8 ; 0x4a6 49e: 10 33 cpi r17, 0x30 ; 48 4a0: 09 f0 breq .+2 ; 0x4a4 4a2: 41 c0 rjmp .+130 ; 0x526 4a4: 21 c0 rjmp .+66 ; 0x4e8 4a6: 15 34 cpi r17, 0x45 ; 69 4a8: 11 f1 breq .+68 ; 0x4ee 4aa: 19 34 cpi r17, 0x49 ; 73 4ac: e1 f5 brne .+120 ; 0x526 4ae: 24 c0 rjmp .+72 ; 0x4f8 4b0: 15 35 cpi r17, 0x55 ; 85 4b2: 91 f0 breq .+36 ; 0x4d8 4b4: 16 35 cpi r17, 0x56 ; 86 4b6: 28 f4 brcc .+10 ; 0x4c2 4b8: 10 35 cpi r17, 0x50 ; 80 4ba: 61 f0 breq .+24 ; 0x4d4 4bc: 14 35 cpi r17, 0x54 ; 84 4be: 99 f5 brne .+102 ; 0x526 4c0: 20 c0 rjmp .+64 ; 0x502 4c2: 16 35 cpi r17, 0x56 ; 86 4c4: 19 f0 breq .+6 ; 0x4cc 4c6: 17 35 cpi r17, 0x57 ; 87 4c8: 71 f5 brne .+92 ; 0x526 4ca: 2a c0 rjmp .+84 ; 0x520 { case 'V': // Version yackstring(vers); 4cc: 84 e7 ldi r24, 0x74 ; 116 4ce: 90 e0 ldi r25, 0x00 ; 0 4d0: 8e d4 rcall .+2332 ; 0xdee 4d2: 2b c0 rjmp .+86 ; 0x52a c = TRUE; break; case 'P': // Pitch pitch(); 4d4: 6f df rcall .-290 ; 0x3b4 4d6: 29 c0 rjmp .+82 ; 0x52a c = TRUE; break; case 'U': // Tune yackinhibit(OFF); 4d8: 80 e0 ldi r24, 0x00 ; 0 4da: 1d d1 rcall .+570 ; 0x716 yacktune(); 4dc: 9c d4 rcall .+2360 ; 0xe16 yackinhibit(ON); 4de: 81 e0 ldi r24, 0x01 ; 1 4e0: 1a d1 rcall .+564 ; 0x716 4e2: 23 c0 rjmp .+70 ; 0x52a c = TRUE; break; case 'C': // Callsign training cstrain(); 4e4: e2 de rcall .-572 ; 0x2aa 4e6: 21 c0 rjmp .+66 ; 0x52a c = TRUE; break; case '0': // Lock changes yacktoggle(CONFLOCK); 4e8: 82 e0 ldi r24, 0x02 ; 2 4ea: e0 d0 rcall .+448 ; 0x6ac 4ec: 1e c0 rjmp .+60 ; 0x52a c = TRUE; break; case 'E': // Playback Macro 1 yackinhibit(OFF); 4ee: 80 e0 ldi r24, 0x00 ; 0 4f0: 12 d1 rcall .+548 ; 0x716 yackmessage(PLAY,1); 4f2: 82 e0 ldi r24, 0x02 ; 2 4f4: 61 e0 ldi r22, 0x01 ; 1 4f6: 0e c0 rjmp .+28 ; 0x514 timer = YACKSECS(MACTIMEOUT); c = FALSE; break; case 'I': // Playback Macro 2 yackinhibit(OFF); 4f8: 80 e0 ldi r24, 0x00 ; 0 4fa: 0d d1 rcall .+538 ; 0x716 yackmessage(PLAY,2); 4fc: 82 e0 ldi r24, 0x02 ; 2 4fe: 62 e0 ldi r22, 0x02 ; 2 500: 09 c0 rjmp .+18 ; 0x514 timer = YACKSECS(MACTIMEOUT); c = FALSE; break; case 'T': // Playback Macro 3 yackinhibit(OFF); 502: 80 e0 ldi r24, 0x00 ; 0 504: 08 d1 rcall .+528 ; 0x716 yackmessage(PLAY,3); 506: 82 e0 ldi r24, 0x02 ; 2 508: 63 e0 ldi r22, 0x03 ; 3 50a: 04 c0 rjmp .+8 ; 0x514 timer = YACKSECS(MACTIMEOUT); c = FALSE; break; case 'M': // Playback Macro 4 yackinhibit(OFF); 50c: 80 e0 ldi r24, 0x00 ; 0 50e: 03 d1 rcall .+518 ; 0x716 yackmessage(PLAY,4); 510: 82 e0 ldi r24, 0x02 ; 2 512: 64 e0 ldi r22, 0x04 ; 4 514: 84 d3 rcall .+1800 ; 0xc1e yackinhibit(ON); 516: 81 e0 ldi r24, 0x01 ; 1 518: fe d0 rcall .+508 ; 0x716 yackstring(prgx); // Sign off yackinhibit(OFF); // Back to normal mode } 51a: c8 eb ldi r28, 0xB8 ; 184 51c: db e0 ldi r29, 0x0B ; 11 51e: 0e c0 rjmp .+28 ; 0x53c timer = YACKSECS(MACTIMEOUT); c = FALSE; break; case 'W': // Query WPM yacknumber(yackwpm()); 520: 78 d0 rcall .+240 ; 0x612 522: 23 d4 rcall .+2118 ; 0xd6a 524: 02 c0 rjmp .+4 ; 0x52a break; } if (c == TRUE) // If c still contains a string, the command was not handled properly 526: 11 30 cpi r17, 0x01 ; 1 528: 39 f4 brne .+14 ; 0x538 { yacksave(); //Save any non-volatile changes to EEPROM 52a: d9 d2 rcall .+1458 ; 0xade yackdelay(DAHLEN * 3); //Eliminate runon txok on some commands 52c: 89 e0 ldi r24, 0x09 ; 9 52e: 06 d1 rcall .+524 ; 0x73c yackstring(txok); 530: 82 e7 ldi r24, 0x72 ; 114 532: 90 e0 ldi r25, 0x00 ; 0 534: 5c d4 rcall .+2232 ; 0xdee 536: 02 c0 rjmp .+4 ; 0x53c } else if (c) 538: 11 11 cpse r17, r1 yackerror(); 53a: 34 d1 rcall .+616 ; 0x7a4 yackchar('?'); // Play Greeting timer = YACKSECS(DEFTIMEOUT); // Time out after 10 seconds while ((yackctrlkey(TRUE)==0) && (timer-- > 0)) 53c: 81 e0 ldi r24, 0x01 ; 1 53e: f3 d2 rcall .+1510 ; 0xb26 540: 88 23 and r24, r24 542: 19 f4 brne .+6 ; 0x54a 544: 20 97 sbiw r28, 0x00 ; 0 546: 09 f0 breq .+2 ; 0x54a 548: 5b cf rjmp .-330 ; 0x400 yackerror(); } yackstring(prgx); // Sign off 54a: 8a e7 ldi r24, 0x7A ; 122 54c: 90 e0 ldi r25, 0x00 ; 0 54e: 4f d4 rcall .+2206 ; 0xdee yackinhibit(OFF); // Back to normal mode 550: 80 e0 ldi r24, 0x00 ; 0 552: e1 d0 rcall .+450 ; 0x716 } 554: df 91 pop r29 556: cf 91 pop r28 558: 1f 91 pop r17 55a: 08 95 ret 0000055c
: @return Not relevant */ { yackinit(); // Initialize YACK hardware 55c: 94 d4 rcall .+2344 ; 0xe86 yackinhibit(ON); //side tone greeting to confirm the unit is alive and kicking 55e: 81 e0 ldi r24, 0x01 ; 1 560: da d0 rcall .+436 ; 0x716 yackstring(imok); 562: 8c e7 ldi r24, 0x7C ; 124 564: 90 e0 ldi r25, 0x00 ; 0 566: 43 d4 rcall .+2182 ; 0xdee yackinhibit(OFF); 568: 80 e0 ldi r24, 0x00 ; 0 56a: d5 d0 rcall .+426 ; 0x716 while(1) // Endless core loop of the keyer app { if (yackctrlkey(TRUE)) // If command key pressed, go to command mode 56c: 81 e0 ldi r24, 0x01 ; 1 56e: db d2 rcall .+1462 ; 0xb26 570: 81 11 cpse r24, r1 commandmode(); 572: 3c df rcall .-392 ; 0x3ec yackbeat(); 574: 52 d0 rcall .+164 ; 0x61a beacon(PLAY); // Play beacon if requested 576: 82 e0 ldi r24, 0x02 ; 2 578: 03 de rcall .-1018 ; 0x180 yackiambic(OFF); 57a: 80 e0 ldi r24, 0x00 ; 0 57c: 7a d1 rcall .+756 ; 0x872 57e: f6 cf rjmp .-20 ; 0x56c 00000580 <__vector_2>: This function is called whenever the system is in sleep mode and there is a level change on one of the contacts we are monitoring (dit, dah and the command key). As all handling is already taken care of by polling in the main routines, there is nothing we need to do here. */ { 580: 1f 92 push r1 582: 0f 92 push r0 584: 0f b6 in r0, 0x3f ; 63 586: 0f 92 push r0 588: 11 24 eor r1, r1 // Nothing to do here. All we want is to wake up.. } 58a: 0f 90 pop r0 58c: 0f be out 0x3f, r0 ; 63 58e: 0f 90 pop r0 590: 1f 90 pop r1 592: 18 95 reti 00000594 : */ { static uint32_t shdntimer=0; if (n) // True = we could go to sleep 594: 88 23 and r24, r24 596: 09 f4 brne .+2 ; 0x59a 598: 33 c0 rjmp .+102 ; 0x600 { if(shdntimer++ == YACKSECS(PSTIME)) 59a: 80 91 6f 00 lds r24, 0x006F 59e: 90 91 70 00 lds r25, 0x0070 5a2: a0 91 71 00 lds r26, 0x0071 5a6: b0 91 72 00 lds r27, 0x0072 5aa: 01 96 adiw r24, 0x01 ; 1 5ac: a1 1d adc r26, r1 5ae: b1 1d adc r27, r1 5b0: 80 93 6f 00 sts 0x006F, r24 5b4: 90 93 70 00 sts 0x0070, r25 5b8: a0 93 71 00 sts 0x0071, r26 5bc: b0 93 72 00 sts 0x0072, r27 5c0: 01 97 sbiw r24, 0x01 ; 1 5c2: a1 09 sbc r26, r1 5c4: b1 09 sbc r27, r1 5c6: 80 57 subi r24, 0x70 ; 112 5c8: 97 41 sbci r25, 0x17 ; 23 5ca: a0 40 sbci r26, 0x00 ; 0 5cc: b0 40 sbci r27, 0x00 ; 0 5ce: 01 f5 brne .+64 ; 0x610 { shdntimer=0; // So we do not go to sleep right after waking up.. 5d0: 10 92 6f 00 sts 0x006F, r1 5d4: 10 92 70 00 sts 0x0070, r1 5d8: 10 92 71 00 sts 0x0071, r1 5dc: 10 92 72 00 sts 0x0072, r1 set_sleep_mode(SLEEP_MODE_PWR_DOWN); 5e0: 85 b7 in r24, 0x35 ; 53 5e2: 87 7e andi r24, 0xE7 ; 231 5e4: 80 61 ori r24, 0x10 ; 16 5e6: 85 bf out 0x35, r24 ; 53 sleep_bod_disable(); 5e8: 85 b7 in r24, 0x35 ; 53 5ea: 84 68 ori r24, 0x84 ; 132 5ec: 85 bf out 0x35, r24 ; 53 5ee: 8b 7f andi r24, 0xFB ; 251 5f0: 85 bf out 0x35, r24 ; 53 sleep_enable(); 5f2: 85 b7 in r24, 0x35 ; 53 5f4: 80 62 ori r24, 0x20 ; 32 5f6: 85 bf out 0x35, r24 ; 53 sei(); 5f8: 78 94 sei sleep_cpu(); 5fa: 88 95 sleep cli(); 5fc: f8 94 cli 5fe: 08 95 ret } } else // Passed parameter is FALSE { shdntimer=0; 600: 10 92 6f 00 sts 0x006F, r1 604: 10 92 70 00 sts 0x0070, r1 608: 10 92 71 00 sts 0x0071, r1 60c: 10 92 72 00 sts 0x0072, r1 610: 08 95 ret 00000612 : */ { return wpm; } 612: 80 91 78 00 lds r24, 0x0078 616: 90 e0 ldi r25, 0x00 ; 0 618: 08 95 ret 0000061a : using an interrupt or a timer. For simpler cases this is a busy wait routine that delays exactly YACKBEAT ms. */ { while((TIFR & (1< TIFR |= (1<: @param dir UP or DOWN */ { if (dir == UP) 628: 81 30 cpi r24, 0x01 ; 1 62a: 31 f4 brne .+12 ; 0x638 ctcvalue--; 62c: 80 91 74 00 lds r24, 0x0074 630: 90 91 75 00 lds r25, 0x0075 634: 01 97 sbiw r24, 0x01 ; 1 636: 07 c0 rjmp .+14 ; 0x646 if (dir == DOWN) 638: 82 30 cpi r24, 0x02 ; 2 63a: 49 f4 brne .+18 ; 0x64e ctcvalue++; 63c: 80 91 74 00 lds r24, 0x0074 640: 90 91 75 00 lds r25, 0x0075 644: 01 96 adiw r24, 0x01 ; 1 646: 90 93 75 00 sts 0x0075, r25 64a: 80 93 74 00 sts 0x0074, r24 if (ctcvalue < MAXCTC) 64e: 80 91 74 00 lds r24, 0x0074 652: 90 91 75 00 lds r25, 0x0075 656: 88 97 sbiw r24, 0x28 ; 40 658: 30 f4 brcc .+12 ; 0x666 ctcvalue = MAXCTC; 65a: 88 e2 ldi r24, 0x28 ; 40 65c: 90 e0 ldi r25, 0x00 ; 0 65e: 90 93 75 00 sts 0x0075, r25 662: 80 93 74 00 sts 0x0074, r24 if (ctcvalue > MINCTC) 666: 80 91 74 00 lds r24, 0x0074 66a: 90 91 75 00 lds r25, 0x0075 66e: 8c 39 cpi r24, 0x9C ; 156 670: 91 05 cpc r25, r1 672: 30 f0 brcs .+12 ; 0x680 ctcvalue = MINCTC; 674: 8b e9 ldi r24, 0x9B ; 155 676: 90 e0 ldi r25, 0x00 ; 0 678: 90 93 75 00 sts 0x0075, r25 67c: 80 93 74 00 sts 0x0074, r24 volflags |= DIRTYFLAG; // Set the dirty flag 680: 80 91 66 00 lds r24, 0x0066 684: 84 60 ori r24, 0x04 ; 4 686: 80 93 66 00 sts 0x0066, r24 } 68a: 08 95 ret 0000068c : */ { yackflags &= ~MODE; yackflags |= mode; 68c: 90 91 73 00 lds r25, 0x0073 690: 93 7f andi r25, 0xF3 ; 243 692: 98 2b or r25, r24 694: 90 93 73 00 sts 0x0073, r25 volflags |= DIRTYFLAG; // Set the dirty flag 698: 80 91 66 00 lds r24, 0x0066 69c: 84 60 ori r24, 0x04 ; 4 69e: 80 93 66 00 sts 0x0066, r24 } 6a2: 08 95 ret 000006a4 : @param flag A byte which indicate which flags are to be queried @return 0 if the flag(s) were clear, >0 if flag(s) were set */ { 6a4: 90 91 73 00 lds r25, 0x0073 return yackflags & flag; } 6a8: 89 23 and r24, r25 6aa: 08 95 ret 000006ac : @return TRUE if all was OK, FALSE if configuration lock prevented changes */ { yackflags ^= flag; // Toggle the feature bit 6ac: 90 91 73 00 lds r25, 0x0073 6b0: 98 27 eor r25, r24 6b2: 90 93 73 00 sts 0x0073, r25 volflags |= DIRTYFLAG; // Set the dirty flag 6b6: 80 91 66 00 lds r24, 0x0066 6ba: 84 60 ori r24, 0x04 ; 4 6bc: 80 93 66 00 sts 0x0066, r24 } 6c0: 08 95 ret 000006c2 : This is a private function. @param mode UP or DOWN */ { 6c2: 98 2f mov r25, r24 if (mode == DOWN) 6c4: 82 30 cpi r24, 0x02 ; 2 6c6: a9 f4 brne .+42 ; 0x6f2 { if (volflags & SIDETONE) // Are we generating a Sidetone? 6c8: 80 91 66 00 lds r24, 0x0066 6cc: 28 2f mov r18, r24 6ce: 84 ff sbrs r24, 4 6d0: 08 c0 rjmp .+16 ; 0x6e2 { OCR0A = ctcvalue; // Then switch on the Sidetone generator 6d2: 80 91 74 00 lds r24, 0x0074 6d6: 89 bd out 0x29, r24 ; 41 OCR0B = ctcvalue; 6d8: 88 bd out 0x28, r24 ; 40 // Activate CTC mode TCCR0A |= (1< { if (yackflags & TXINV) // Do we need to invert keying? 6e6: 80 91 73 00 lds r24, 0x0073 6ea: 86 ff sbrs r24, 6 6ec: 10 c0 rjmp .+32 ; 0x70e CLEARBIT(OUTPORT,OUTPIN); 6ee: c0 98 cbi 0x18, 0 ; 24 6f0: 08 95 ret SETBIT(OUTPORT,OUTPIN); } } if (mode == UP) 6f2: 81 30 cpi r24, 0x01 ; 1 6f4: 79 f4 brne .+30 ; 0x714 { if (volflags & SIDETONE) // Sidetone active? 6f6: 80 91 66 00 lds r24, 0x0066 6fa: 84 ff sbrs r24, 4 6fc: 02 c0 rjmp .+4 ; 0x702 { TCCR0A = 0; 6fe: 1a bc out 0x2a, r1 ; 42 TCCR0B = 0; 700: 13 be out 0x33, r1 ; 51 } if (volflags & TXKEY) // Are we keying the TX? 702: 85 ff sbrs r24, 5 704: 07 c0 rjmp .+14 ; 0x714 { if (yackflags & TXINV) // Do we need to invert keying? 706: 80 91 73 00 lds r24, 0x0073 70a: 86 ff sbrs r24, 6 70c: 02 c0 rjmp .+4 ; 0x712 SETBIT(OUTPORT,OUTPIN); 70e: c0 9a sbi 0x18, 0 ; 24 710: 08 95 ret else CLEARBIT(OUTPORT,OUTPIN); 712: c0 98 cbi 0x18, 0 ; 24 714: 08 95 ret 00000716 : sidetone oscillator to be active so that the user can communicate with the keyer. @param mode ON inhibits keying, OFF re-enables keying */ { 716: 90 91 66 00 lds r25, 0x0066 if (mode) 71a: 88 23 and r24, r24 71c: 29 f0 breq .+10 ; 0x728 { volflags &= ~(TXKEY | SIDETONE); volflags |= SIDETONE; 71e: 9f 7c andi r25, 0xCF ; 207 720: 90 61 ori r25, 0x10 ; 16 722: 90 93 66 00 sts 0x0066, r25 726: 08 95 ret else { volflags &= ~(TXKEY | SIDETONE); volflags |= (yackflags & (TXKEY | SIDETONE)); 728: 80 91 73 00 lds r24, 0x0073 72c: 80 73 andi r24, 0x30 ; 48 72e: 9f 7c andi r25, 0xCF ; 207 730: 89 2b or r24, r25 732: 80 93 66 00 sts 0x0066, r24 key(UP); 736: 81 e0 ldi r24, 0x01 ; 1 738: c4 df rcall .-120 ; 0x6c2 73a: 08 95 ret 0000073c : This is used during the playback functions where active waiting is needed @param n number of dot durations to delay (dependent on current keying speed! */ { 73c: 28 2f mov r18, r24 byte i=n; byte x; while (i--) { x=wpmcnt; 73e: 30 91 76 00 lds r19, 0x0076 742: 0a c0 rjmp .+20 ; 0x758 using an interrupt or a timer. For simpler cases this is a busy wait routine that delays exactly YACKBEAT ms. */ { while((TIFR & (1< TIFR |= (1< 756: 21 50 subi r18, 0x01 ; 1 { byte i=n; byte x; while (i--) 758: 22 23 and r18, r18 75a: 11 f0 breq .+4 ; 0x760 75c: 93 2f mov r25, r19 75e: f9 cf rjmp .-14 ; 0x752 760: 08 95 ret 00000762 : void yackfarns(void) /*! @brief Produces an additional waiting delay for farnsworth mode. */ { 762: cf 93 push r28 764: df 93 push r29 word i=farnsworth; 766: 80 91 79 00 lds r24, 0x0079 76a: c8 2f mov r28, r24 76c: d0 e0 ldi r29, 0x00 ; 0 76e: 03 c0 rjmp .+6 ; 0x776 while (i--) { yackdelay(1); 770: 81 e0 ldi r24, 0x01 ; 1 772: e4 df rcall .-56 ; 0x73c 774: 21 97 sbiw r28, 0x01 ; 1 */ { word i=farnsworth; while (i--) 776: 20 97 sbiw r28, 0x00 ; 0 778: d9 f7 brne .-10 ; 0x770 { yackdelay(1); } } 77a: df 91 pop r29 77c: cf 91 pop r28 77e: 08 95 ret 00000780 : @brief Key the TX / Sidetone for the duration of a dit or a dah @param i DIT or DAH */ { 780: 1f 93 push r17 782: 18 2f mov r17, r24 key(DOWN); 784: 82 e0 ldi r24, 0x02 ; 2 786: 9d df rcall .-198 ; 0x6c2 #ifdef POWERSAVE yackpower(FALSE); // Avoid powerdowns when keying 788: 80 e0 ldi r24, 0x00 ; 0 78a: 04 df rcall .-504 ; 0x594 #endif switch (i) 78c: 11 30 cpi r17, 0x01 ; 1 78e: 21 f0 breq .+8 ; 0x798 790: 12 30 cpi r17, 0x02 ; 2 792: 21 f4 brne .+8 ; 0x79c { case DAH: yackdelay(DAHLEN); 794: 83 e0 ldi r24, 0x03 ; 3 796: 01 c0 rjmp .+2 ; 0x79a break; case DIT: yackdelay(DITLEN); 798: 81 e0 ldi r24, 0x01 ; 1 79a: d0 df rcall .-96 ; 0x73c break; } key(UP); 79c: 81 e0 ldi r24, 0x01 ; 1 79e: 91 df rcall .-222 ; 0x6c2 } 7a0: 1f 91 pop r17 7a2: 08 95 ret 000007a4 : The error prosign (8 dits) can not be encoded in our coding table. A call to this function produces it.. */ { 7a4: 1f 93 push r17 7a6: 10 e0 ldi r17, 0x00 ; 0 byte i; for (i=0;i<8;i++) { yackplay(DIT); 7a8: 81 e0 ldi r24, 0x01 ; 1 7aa: ea df rcall .-44 ; 0x780 yackdelay(DITLEN); 7ac: 81 e0 ldi r24, 0x01 ; 1 7ae: c6 df rcall .-116 ; 0x73c */ { byte i; for (i=0;i<8;i++) 7b0: 1f 5f subi r17, 0xFF ; 255 7b2: 18 30 cpi r17, 0x08 ; 8 7b4: c9 f7 brne .-14 ; 0x7a8 { yackplay(DIT); yackdelay(DITLEN); } yackdelay(DAHLEN); 7b6: 83 e0 ldi r24, 0x03 ; 3 7b8: c1 df rcall .-126 ; 0x73c } 7ba: 1f 91 pop r17 7bc: 08 95 ret 000007be : @param dir UP (faster) or DOWN (slower) */ { if (mode == FARNSWORTH) 7be: 61 30 cpi r22, 0x01 ; 1 7c0: 91 f4 brne .+36 ; 0x7e6 { if ((dir == UP) && (farnsworth > 0)) 7c2: 81 30 cpi r24, 0x01 ; 1 7c4: 31 f4 brne .+12 ; 0x7d2 7c6: 80 91 79 00 lds r24, 0x0079 7ca: 88 23 and r24, r24 7cc: 39 f1 breq .+78 ; 0x81c farnsworth--; 7ce: 81 50 subi r24, 0x01 ; 1 7d0: 07 c0 rjmp .+14 ; 0x7e0 if ((dir == DOWN) && (farnsworth < MAXFARN)) 7d2: 82 30 cpi r24, 0x02 ; 2 7d4: 19 f5 brne .+70 ; 0x81c 7d6: 80 91 79 00 lds r24, 0x0079 7da: 8f 3f cpi r24, 0xFF ; 255 7dc: f9 f0 breq .+62 ; 0x81c farnsworth++; 7de: 8f 5f subi r24, 0xFF ; 255 7e0: 80 93 79 00 sts 0x0079, r24 7e4: 1b c0 rjmp .+54 ; 0x81c } else // WPMSPEED { if ((dir == UP) && (wpm < MAXWPM)) 7e6: 81 30 cpi r24, 0x01 ; 1 7e8: 31 f4 brne .+12 ; 0x7f6 7ea: 80 91 78 00 lds r24, 0x0078 7ee: 82 33 cpi r24, 0x32 ; 50 7f0: 58 f4 brcc .+22 ; 0x808 wpm++; 7f2: 8f 5f subi r24, 0xFF ; 255 7f4: 07 c0 rjmp .+14 ; 0x804 if ((dir == DOWN) && (wpm > MINWPM)) 7f6: 82 30 cpi r24, 0x02 ; 2 7f8: 39 f4 brne .+14 ; 0x808 7fa: 80 91 78 00 lds r24, 0x0078 7fe: 86 30 cpi r24, 0x06 ; 6 800: 18 f0 brcs .+6 ; 0x808 wpm--; 802: 81 50 subi r24, 0x01 ; 1 804: 80 93 78 00 sts 0x0078, r24 wpmcnt=(1200/YACKBEAT)/wpm; // Calculate beats 808: 60 91 78 00 lds r22, 0x0078 80c: 80 ef ldi r24, 0xF0 ; 240 80e: 90 e0 ldi r25, 0x00 ; 0 810: 70 e0 ldi r23, 0x00 ; 0 812: 9a d3 rcall .+1844 ; 0xf48 <__divmodhi4> 814: 70 93 77 00 sts 0x0077, r23 818: 60 93 76 00 sts 0x0076, r22 } volflags |= DIRTYFLAG; // Set the dirty flag 81c: 80 91 66 00 lds r24, 0x0066 820: 84 60 ori r24, 0x04 ; 4 822: 80 93 66 00 sts 0x0066, r24 yackplay(DIT); 826: 81 e0 ldi r24, 0x01 ; 1 828: ab df rcall .-170 ; 0x780 yackdelay(IEGLEN); // Inter Element gap 82a: 81 e0 ldi r24, 0x01 ; 1 82c: 87 df rcall .-242 ; 0x73c yackplay(DAH); 82e: 82 e0 ldi r24, 0x02 ; 2 830: a7 df rcall .-178 ; 0x780 yackdelay(ICGLEN); // Inter Character gap 832: 83 e0 ldi r24, 0x03 ; 3 834: 83 df rcall .-250 ; 0x73c yackfarns(); // Additional Farnsworth delay 836: 95 df rcall .-214 ; 0x762 } 838: 08 95 ret 0000083a : */ { byte swap; // Status of swap flag swap = ( yackflags & PDLSWAP); 83a: 90 91 73 00 lds r25, 0x0073 83e: 90 78 andi r25, 0x80 ; 128 if (!( KEYINP & (1< volflags |= (swap?DAHLATCH:DITLATCH); 844: 20 91 66 00 lds r18, 0x0066 848: 99 23 and r25, r25 84a: 11 f4 brne .+4 ; 0x850 84c: 81 e0 ldi r24, 0x01 ; 1 84e: 01 c0 rjmp .+2 ; 0x852 850: 82 e0 ldi r24, 0x02 ; 2 852: 82 2b or r24, r18 854: 80 93 66 00 sts 0x0066, r24 if (!( KEYINP & (1< volflags |= (swap?DITLATCH:DAHLATCH); 85c: 20 91 66 00 lds r18, 0x0066 860: 99 23 and r25, r25 862: 11 f4 brne .+4 ; 0x868 864: 82 e0 ldi r24, 0x02 ; 2 866: 01 c0 rjmp .+2 ; 0x86a 868: 81 e0 ldi r24, 0x01 ; 1 86a: 82 2b or r24, r18 86c: 80 93 66 00 sts 0x0066, r24 870: 08 95 ret 00000872 : @param ctrl ON if the keyer should recognize when a word ends. OFF if not. @return The character if one was recognized, /0 if not */ { 872: 1f 93 push r17 // If the FSM remains in idle state for another 4 dot times (7 dot times // altogether), we assume that the word has ended. A space char // is transmitted in this case. if (timer) timer--; // Count down 874: 20 91 6c 00 lds r18, 0x006C 878: 30 91 6d 00 lds r19, 0x006D 87c: 21 15 cp r18, r1 87e: 31 05 cpc r19, r1 880: 31 f0 breq .+12 ; 0x88e 882: 21 50 subi r18, 0x01 ; 1 884: 30 40 sbci r19, 0x00 ; 0 886: 30 93 6d 00 sts 0x006D, r19 88a: 20 93 6c 00 sts 0x006C, r18 if (ctrl == OFF) iwgflag = 0; // No space detection 88e: 88 23 and r24, r24 890: 11 f4 brne .+4 ; 0x896 892: 10 92 68 00 sts 0x0068, r1 switch (fsms) 896: 80 91 6e 00 lds r24, 0x006E 89a: 81 30 cpi r24, 0x01 ; 1 89c: 09 f4 brne .+2 ; 0x8a0 89e: ce c0 rjmp .+412 ; 0xa3c 8a0: 81 30 cpi r24, 0x01 ; 1 8a2: 20 f0 brcs .+8 ; 0x8ac 8a4: 82 30 cpi r24, 0x02 ; 2 8a6: 09 f0 breq .+2 ; 0x8aa 8a8: f6 c0 rjmp .+492 ; 0xa96 8aa: e4 c0 rjmp .+456 ; 0xa74 { case IDLE: keylatch(); 8ac: c6 df rcall .-116 ; 0x83a #ifdef POWERSAVE yackpower(TRUE); // OK to go to sleep when here. 8ae: 81 e0 ldi r24, 0x01 ; 1 8b0: 71 de rcall .-798 ; 0x594 #endif // Handle latching logic for various keyer modes switch (yackflags & MODE) 8b2: 80 91 73 00 lds r24, 0x0073 8b6: 90 e0 ldi r25, 0x00 ; 0 8b8: 8c 70 andi r24, 0x0C ; 12 8ba: 90 70 andi r25, 0x00 ; 0 8bc: 84 30 cpi r24, 0x04 ; 4 8be: 91 05 cpc r25, r1 8c0: 61 f0 breq .+24 ; 0x8da 8c2: 85 30 cpi r24, 0x05 ; 5 8c4: 91 05 cpc r25, r1 8c6: 1c f4 brge .+6 ; 0x8ce 8c8: 89 2b or r24, r25 8ca: 39 f0 breq .+14 ; 0x8da 8cc: 2d c0 rjmp .+90 ; 0x928 8ce: 88 30 cpi r24, 0x08 ; 8 8d0: 91 05 cpc r25, r1 8d2: 71 f0 breq .+28 ; 0x8f0 8d4: 0c 97 sbiw r24, 0x0c ; 12 8d6: 41 f5 brne .+80 ; 0x928 8d8: 1e c0 rjmp .+60 ; 0x916 // When the paddle keys are squeezed, we need to ensure that // dots and dashes are alternating. To do that, whe delete // any latched paddle of the same kind that we just sent. // However, we only do this ONCE volflags &= ~lastsymbol; 8da: 90 91 6b 00 lds r25, 0x006B 8de: 90 95 com r25 8e0: 80 91 66 00 lds r24, 0x0066 8e4: 89 23 and r24, r25 8e6: 80 93 66 00 sts 0x0066, r24 lastsymbol = 0; 8ea: 10 92 6b 00 sts 0x006B, r1 8ee: 1c c0 rjmp .+56 ; 0x928 break; case ULTIMATIC: // Ultimatic logic: The last paddle to be active will be repeated indefinitely // In case the keyer is squeezed right out of idle mode, we just send a DAH if ((volflags & SQUEEZED) == SQUEEZED) // Squeezed? 8f0: 90 91 66 00 lds r25, 0x0066 8f4: 89 2f mov r24, r25 8f6: 83 70 andi r24, 0x03 ; 3 8f8: 83 30 cpi r24, 0x03 ; 3 8fa: 49 f4 brne .+18 ; 0x90e { if (ultimem) 8fc: 80 91 67 00 lds r24, 0x0067 900: 88 23 and r24, r24 902: 79 f0 breq .+30 ; 0x922 volflags &= ~ultimem; // Opposite symbol from last one 904: 80 95 com r24 906: 89 23 and r24, r25 908: 80 93 66 00 sts 0x0066, r24 90c: 0d c0 rjmp .+26 ; 0x928 else volflags &= ~DITLATCH; // Reset the DIT latch } else { ultimem = volflags & SQUEEZED; // Remember the last single key 90e: 93 70 andi r25, 0x03 ; 3 910: 90 93 67 00 sts 0x0067, r25 914: 09 c0 rjmp .+18 ; 0x928 break; case DAHPRIO: // If both paddles pressed, DAH is given priority if ((volflags & SQUEEZED) == SQUEEZED) 916: 90 91 66 00 lds r25, 0x0066 91a: 89 2f mov r24, r25 91c: 83 70 andi r24, 0x03 ; 3 91e: 83 30 cpi r24, 0x03 ; 3 920: 19 f4 brne .+6 ; 0x928 { volflags &= ~DITLATCH; // Reset the DIT latch 922: 9e 7f andi r25, 0xFE ; 254 924: 90 93 66 00 sts 0x0066, r25 // The following handles the inter-character gap. When there are // three (default) dot lengths of space after an element, the // character is complete and can be returned to caller if (timer == 0 && bcntr != 0) // Have we idled for 3 dots 928: 80 91 6c 00 lds r24, 0x006C 92c: 90 91 6d 00 lds r25, 0x006D 930: 89 2b or r24, r25 932: 09 f0 breq .+2 ; 0x936 934: 4b c0 rjmp .+150 ; 0x9cc 936: 40 91 69 00 lds r20, 0x0069 93a: 44 23 and r20, r20 93c: 09 f4 brne .+2 ; 0x940 93e: 3e c0 rjmp .+124 ; 0x9bc // and is there something to decode? { buffer = buffer << 1; // Make space for the termination bit buffer |= 1; // The 1 on the right signals end buffer = buffer << (7-bcntr); // Shift to left justify 940: 80 91 6a 00 lds r24, 0x006A 944: 88 0f add r24, r24 946: 81 60 ori r24, 0x01 ; 1 948: 90 e0 ldi r25, 0x00 ; 0 94a: 27 e0 ldi r18, 0x07 ; 7 94c: 30 e0 ldi r19, 0x00 ; 0 94e: 24 1b sub r18, r20 950: 31 09 sbc r19, r1 952: 02 c0 rjmp .+4 ; 0x958 954: 88 0f add r24, r24 956: 99 1f adc r25, r25 958: 2a 95 dec r18 95a: e2 f7 brpl .-8 ; 0x954 95c: 98 2f mov r25, r24 95e: 20 e0 ldi r18, 0x00 ; 0 960: 30 e0 ldi r19, 0x00 ; 0 byte i; for(i=0;i { if (i < 10) return ('0' + i); // First 10 chars are digits 96e: 2a 30 cpi r18, 0x0A ; 10 970: 10 f4 brcc .+4 ; 0x976 972: 20 5d subi r18, 0xD0 ; 208 974: 0f c0 rjmp .+30 ; 0x994 if (i < 36) return ('A' + i - 10); // Then follow letters 976: 24 32 cpi r18, 0x24 ; 36 978: 10 f4 brcc .+4 ; 0x97e 97a: 29 5c subi r18, 0xC9 ; 201 97c: 0b c0 rjmp .+22 ; 0x994 return (pgm_read_byte(&spechar[i - 36])); // Then special chars 97e: 29 56 subi r18, 0x69 ; 105 980: 3f 4f sbci r19, 0xFF ; 255 982: f9 01 movw r30, r18 984: 24 91 lpm r18, Z+ 986: 06 c0 rjmp .+12 ; 0x994 988: 2f 5f subi r18, 0xFF ; 255 98a: 3f 4f sbci r19, 0xFF ; 255 */ { byte i; for(i=0;i 992: 20 e0 ldi r18, 0x00 ; 0 { buffer = buffer << 1; // Make space for the termination bit buffer |= 1; // The 1 on the right signals end buffer = buffer << (7-bcntr); // Shift to left justify retchar = morsechar(buffer); // Attempt decoding buffer = bcntr = 0; // Clear buffer 994: 10 92 69 00 sts 0x0069, r1 998: 10 92 6a 00 sts 0x006A, r1 timer = (IWGLEN - ICGLEN) * wpmcnt; // If 4 further dots of gap, 99c: 80 91 76 00 lds r24, 0x0076 9a0: 90 91 77 00 lds r25, 0x0077 9a4: 88 0f add r24, r24 9a6: 99 1f adc r25, r25 9a8: 88 0f add r24, r24 9aa: 99 1f adc r25, r25 9ac: 90 93 6d 00 sts 0x006D, r25 9b0: 80 93 6c 00 sts 0x006C, r24 // this might be a Word gap. iwgflag = 1; // Signal we are waiting for IWG 9b4: 81 e0 ldi r24, 0x01 ; 1 9b6: 80 93 68 00 sts 0x0068, r24 9ba: 6e c0 rjmp .+220 ; 0xa98 return (retchar); // and return decoded char } // This handles the Inter-word gap. Already 3 dots have been // waited for, if 4 more follow, interpret this as a word end if (timer == 0 && iwgflag) // Have we idled for 4+3 = 7 dots? 9bc: 80 91 68 00 lds r24, 0x0068 9c0: 88 23 and r24, r24 9c2: 21 f0 breq .+8 ; 0x9cc { iwgflag = 0; // Clear Interword Gap flag 9c4: 10 92 68 00 sts 0x0068, r1 9c8: 20 e2 ldi r18, 0x20 ; 32 9ca: 66 c0 rjmp .+204 ; 0xa98 return (' '); // And return a space } // Now evaluate the latch and determine what to send next if ( volflags & (DITLATCH | DAHLATCH)) // Anything in the latch? 9cc: 10 91 66 00 lds r17, 0x0066 9d0: 41 2f mov r20, r17 9d2: 50 e0 ldi r21, 0x00 ; 0 9d4: ca 01 movw r24, r20 9d6: 83 70 andi r24, 0x03 ; 3 9d8: 90 70 andi r25, 0x00 ; 0 9da: 89 2b or r24, r25 9dc: 09 f4 brne .+2 ; 0x9e0 9de: 5b c0 rjmp .+182 ; 0xa96 { iwgflag = 0; // No interword gap if dit or dah 9e0: 10 92 68 00 sts 0x0068, r1 bcntr++; // Count that we will send something now 9e4: 80 91 69 00 lds r24, 0x0069 9e8: 8f 5f subi r24, 0xFF ; 255 9ea: 80 93 69 00 sts 0x0069, r24 buffer = buffer << 1; // Make space for the new character 9ee: 20 91 6a 00 lds r18, 0x006A 9f2: 22 0f add r18, r18 9f4: 20 93 6a 00 sts 0x006A, r18 9f8: 80 91 76 00 lds r24, 0x0076 9fc: 90 91 77 00 lds r25, 0x0077 if (volflags & DITLATCH) // Is it a dit? a00: 10 ff sbrs r17, 0 a02: 08 c0 rjmp .+16 ; 0xa14 { timer = DITLEN * wpmcnt; // Duration = one dot time a04: 90 93 6d 00 sts 0x006D, r25 a08: 80 93 6c 00 sts 0x006C, r24 lastsymbol = DITLATCH; // Remember what we sent a0c: 81 e0 ldi r24, 0x01 ; 1 a0e: 80 93 6b 00 sts 0x006B, r24 a12: 0d c0 rjmp .+26 ; 0xa2e } else // must be a DAH then.. { timer = DAHLEN * wpmcnt; // Duration = one dash time a14: 63 e0 ldi r22, 0x03 ; 3 a16: 70 e0 ldi r23, 0x00 ; 0 a18: 71 d2 rcall .+1250 ; 0xefc <__mulhi3> a1a: 90 93 6d 00 sts 0x006D, r25 a1e: 80 93 6c 00 sts 0x006C, r24 lastsymbol = DAHLATCH; // Remember a22: 82 e0 ldi r24, 0x02 ; 2 a24: 80 93 6b 00 sts 0x006B, r24 buffer |= 1; // set LSB to remember dash a28: 21 60 ori r18, 0x01 ; 1 a2a: 20 93 6a 00 sts 0x006A, r18 } key(DOWN); // Switch on the side tone and TX a2e: 82 e0 ldi r24, 0x02 ; 2 a30: 48 de rcall .-880 ; 0x6c2 volflags &= ~(DITLATCH | DAHLATCH); // Reset both latches a32: 1c 7f andi r17, 0xFC ; 252 a34: 10 93 66 00 sts 0x0066, r17 fsms = KEYED; // Change FSM state a38: 81 e0 ldi r24, 0x01 ; 1 a3a: 19 c0 rjmp .+50 ; 0xa6e case KEYED: #ifdef POWERSAVE yackpower(FALSE); // can not go to sleep when keyed a3c: 80 e0 ldi r24, 0x00 ; 0 a3e: aa dd rcall .-1196 ; 0x594 #endif if ((yackflags & MODE) == IAMBICB) // If we are in IAMBIC B mode a40: 80 91 73 00 lds r24, 0x0073 a44: 8c 70 andi r24, 0x0C ; 12 a46: 84 30 cpi r24, 0x04 ; 4 a48: 09 f4 brne .+2 ; 0xa4c keylatch(); // then latch here already a4a: f7 de rcall .-530 ; 0x83a if(timer == 0) // Done with sounding our element? a4c: 80 91 6c 00 lds r24, 0x006C a50: 90 91 6d 00 lds r25, 0x006D a54: 89 2b or r24, r25 a56: f9 f4 brne .+62 ; 0xa96 { key(UP); // Then cancel the side tone a58: 81 e0 ldi r24, 0x01 ; 1 a5a: 33 de rcall .-922 ; 0x6c2 timer = IEGLEN * wpmcnt; // One dot time for the gap a5c: 80 91 76 00 lds r24, 0x0076 a60: 90 91 77 00 lds r25, 0x0077 a64: 90 93 6d 00 sts 0x006D, r25 a68: 80 93 6c 00 sts 0x006C, r24 fsms = IEG; // Change FSM state a6c: 82 e0 ldi r24, 0x02 ; 2 a6e: 80 93 6e 00 sts 0x006E, r24 a72: 11 c0 rjmp .+34 ; 0xa96 break; case IEG: keylatch(); // Latch any paddle movements (both A and B) a74: e2 de rcall .-572 ; 0x83a if(timer == 0) // End of gap reached? a76: 80 91 6c 00 lds r24, 0x006C a7a: 90 91 6d 00 lds r25, 0x006D a7e: 89 2b or r24, r25 a80: 51 f4 brne .+20 ; 0xa96 { fsms = IDLE; // Change FSM state a82: 10 92 6e 00 sts 0x006E, r1 // The following timer determines what the IDLE state // accepts as character. Anything longer than 2 dots as gap will be // accepted for a character end. timer = (ICGLEN - IEGLEN -1) * wpmcnt; a86: 80 91 76 00 lds r24, 0x0076 a8a: 90 91 77 00 lds r25, 0x0077 a8e: 90 93 6d 00 sts 0x006D, r25 a92: 80 93 6c 00 sts 0x006C, r24 a96: 20 e0 ldi r18, 0x00 ; 0 } return '\0'; // Nothing to return if not returned in above routine } a98: 82 2f mov r24, r18 a9a: 1f 91 pop r17 a9c: 08 95 ret 00000a9e : */ { if (func == READ) a9e: 81 30 cpi r24, 0x01 ; 1 aa0: 69 f4 brne .+26 ; 0xabc { if (nr == 1) aa2: 61 30 cpi r22, 0x01 ; 1 aa4: 21 f4 brne .+8 ; 0xaae return (eeprom_read_word(&user1)); aa6: 86 e0 ldi r24, 0x06 ; 6 aa8: 90 e0 ldi r25, 0x00 ; 0 aaa: 79 d2 rcall .+1266 ; 0xf9e <__eerd_word_tn85> aac: 05 c0 rjmp .+10 ; 0xab8 else if (nr == 2) aae: 62 30 cpi r22, 0x02 ; 2 ab0: 91 f4 brne .+36 ; 0xad6 return (eeprom_read_word(&user2)); ab2: 88 e0 ldi r24, 0x08 ; 8 ab4: 90 e0 ldi r25, 0x00 ; 0 ab6: 73 d2 rcall .+1254 ; 0xf9e <__eerd_word_tn85> ab8: 9c 01 movw r18, r24 aba: 0f c0 rjmp .+30 ; 0xada } if (func == WRITE) abc: 82 30 cpi r24, 0x02 ; 2 abe: 59 f4 brne .+22 ; 0xad6 { if (nr == 1) ac0: 61 30 cpi r22, 0x01 ; 1 ac2: 19 f4 brne .+6 ; 0xaca eeprom_write_word(&user1, content); ac4: 86 e0 ldi r24, 0x06 ; 6 ac6: 90 e0 ldi r25, 0x00 ; 0 ac8: 04 c0 rjmp .+8 ; 0xad2 else if (nr == 2) aca: 62 30 cpi r22, 0x02 ; 2 acc: 21 f4 brne .+8 ; 0xad6 eeprom_write_word(&user2, content); ace: 88 e0 ldi r24, 0x08 ; 8 ad0: 90 e0 ldi r25, 0x00 ; 0 ad2: ba 01 movw r22, r20 ad4: 80 d2 rcall .+1280 ; 0xfd6 <__eewr_word_tn85> ad6: 20 e0 ldi r18, 0x00 ; 0 ad8: 30 e0 ldi r19, 0x00 ; 0 } return (FALSE); } ada: c9 01 movw r24, r18 adc: 08 95 ret 00000ade : @callergraph */ { if(volflags & DIRTYFLAG) // Dirty flag set? ade: 80 91 66 00 lds r24, 0x0066 ae2: 82 ff sbrs r24, 2 ae4: 1f c0 rjmp .+62 ; 0xb24 { eeprom_write_byte(&magic, MAGPAT); ae6: 80 e0 ldi r24, 0x00 ; 0 ae8: 90 e0 ldi r25, 0x00 ; 0 aea: 65 ea ldi r22, 0xA5 ; 165 aec: 66 d2 rcall .+1228 ; 0xfba <__eewr_byte_tn85> eeprom_write_word(&ctcstor, ctcvalue); aee: 60 91 74 00 lds r22, 0x0074 af2: 70 91 75 00 lds r23, 0x0075 af6: 82 e0 ldi r24, 0x02 ; 2 af8: 90 e0 ldi r25, 0x00 ; 0 afa: 6d d2 rcall .+1242 ; 0xfd6 <__eewr_word_tn85> eeprom_write_byte(&wpmstor, wpm); afc: 84 e0 ldi r24, 0x04 ; 4 afe: 90 e0 ldi r25, 0x00 ; 0 b00: 60 91 78 00 lds r22, 0x0078 b04: 5a d2 rcall .+1204 ; 0xfba <__eewr_byte_tn85> eeprom_write_byte(&flagstor, yackflags); b06: 81 e0 ldi r24, 0x01 ; 1 b08: 90 e0 ldi r25, 0x00 ; 0 b0a: 60 91 73 00 lds r22, 0x0073 b0e: 55 d2 rcall .+1194 ; 0xfba <__eewr_byte_tn85> eeprom_write_byte(&fwstor, farnsworth); b10: 85 e0 ldi r24, 0x05 ; 5 b12: 90 e0 ldi r25, 0x00 ; 0 b14: 60 91 79 00 lds r22, 0x0079 b18: 50 d2 rcall .+1184 ; 0xfba <__eewr_byte_tn85> volflags &= ~DIRTYFLAG; // Clear the dirty flag b1a: 80 91 66 00 lds r24, 0x0066 b1e: 8b 7f andi r24, 0xFB ; 251 b20: 80 93 66 00 sts 0x0066, r24 b24: 08 95 ret 00000b26 : @return TRUE if a press of the command key is not yet handled. @callergraph */ { b26: 0f 93 push r16 b28: 1f 93 push r17 b2a: 08 2f mov r16, r24 byte volbfr; volbfr = volflags; // Remember current volatile settings b2c: 10 91 66 00 lds r17, 0x0066 if (!(BTNINP & (1< { volbfr |= CKLATCH; // Set control key latch b34: 18 60 ori r17, 0x08 ; 8 // We will now wait a short while and then busy wait until the key is // released. // Should we find that someone is keying the paddle, let him change // the speed and pretend ctrl was never pressed in the first place.. yackinhibit(ON); // Stop keying, switch on sidetone. b36: 81 e0 ldi r24, 0x01 ; 1 b38: ee dd rcall .-1060 ; 0x716 milliseconds can be achieved. */ void _delay_loop_2(uint16_t __count) { __asm__ volatile ( b3a: 84 ed ldi r24, 0xD4 ; 212 b3c: 90 e3 ldi r25, 0x30 ; 48 b3e: 01 97 sbiw r24, 0x01 ; 1 b40: f1 f7 brne .-4 ; 0xb3e b42: 0c c0 rjmp .+24 ; 0xb5c _delay_ms(50); while(!(BTNINP & (1< { yackspeed(DOWN,WPMSPEED); b48: 82 e0 ldi r24, 0x02 ; 2 b4a: 60 e0 ldi r22, 0x00 ; 0 b4c: 38 de rcall .-912 ; 0x7be volbfr &= ~(CKLATCH); // Ignore that control key was pressed b4e: 17 7f andi r17, 0xF7 ; 247 } if (!( KEYINP & (1< { yackspeed(UP,WPMSPEED); b54: 81 e0 ldi r24, 0x01 ; 1 b56: 60 e0 ldi r22, 0x00 ; 0 b58: 32 de rcall .-924 ; 0x7be volbfr &= ~(CKLATCH); b5a: 17 7f andi r17, 0xF7 ; 247 yackinhibit(ON); // Stop keying, switch on sidetone. _delay_ms(50); while(!(BTNINP & (1< b60: 84 ed ldi r24, 0xD4 ; 212 b62: 90 e3 ldi r25, 0x30 ; 48 b64: 01 97 sbiw r24, 0x01 ; 1 b66: f1 f7 brne .-4 ; 0xb64 } _delay_ms(50); // Trailing edge debounce yacksave(); // In case we had a speed change b68: ba df rcall .-140 ; 0xade } volflags = volbfr; // Restore previous state b6a: 10 93 66 00 sts 0x0066, r17 if (mode==TRUE) // Does caller want us to reset latch? b6e: 01 30 cpi r16, 0x01 ; 1 b70: 21 f4 brne .+8 ; 0xb7a { volflags &= ~(CKLATCH); b72: 81 2f mov r24, r17 b74: 87 7f andi r24, 0xF7 ; 247 b76: 80 93 66 00 sts 0x0066, r24 b7a: 81 2f mov r24, r17 b7c: 90 e0 ldi r25, 0x00 ; 0 b7e: 43 e0 ldi r20, 0x03 ; 3 b80: 96 95 lsr r25 b82: 87 95 ror r24 b84: 4a 95 dec r20 b86: e1 f7 brne .-8 ; 0xb80 //yacksave(); // In case we had a speed change (Does NOT work if command is here - moved immediately after button release debounce) return((volbfr&CKLATCH)!=0); // Tell caller if we had a ctrl button press } b88: 81 70 andi r24, 0x01 ; 1 b8a: 1f 91 pop r17 b8c: 0f 91 pop r16 b8e: 08 95 ret 00000b90 : @param c The character to send */ { b90: 1f 93 push r17 b92: 28 2f mov r18, r24 byte code=0x80; // 0x80 is an empty morse character (just eoc bit set) byte i; // a counter // First we need to map the actual character to the encoded morse sequence in // the array "morse" if(c>='0' && c<='9') // Is it a numerical digit? b94: 80 53 subi r24, 0x30 ; 48 b96: 8a 30 cpi r24, 0x0A ; 10 b98: 10 f0 brcs .+4 ; 0xb9e b9a: 10 e8 ldi r17, 0x80 ; 128 b9c: 05 c0 rjmp .+10 ; 0xba8 code = pgm_read_byte(&morse[c-'0']); // Find it in the beginning of array b9e: e2 2f mov r30, r18 ba0: f0 e0 ldi r31, 0x00 ; 0 ba2: e1 5b subi r30, 0xB1 ; 177 ba4: ff 4f sbci r31, 0xFF ; 255 ba6: 14 91 lpm r17, Z+ if(c>='a' && c<='z') // Is it a character? ba8: 82 2f mov r24, r18 baa: 81 56 subi r24, 0x61 ; 97 bac: 8a 31 cpi r24, 0x1A ; 26 bae: 28 f4 brcc .+10 ; 0xbba code = pgm_read_byte(&morse[c-'a'+10]); // Find it from position 10 bb0: e2 2f mov r30, r18 bb2: f0 e0 ldi r31, 0x00 ; 0 bb4: e8 5d subi r30, 0xD8 ; 216 bb6: ff 4f sbci r31, 0xFF ; 255 bb8: 14 91 lpm r17, Z+ if(c>='A' && c<='Z') // Is it a character in upper case? bba: 82 2f mov r24, r18 bbc: 81 54 subi r24, 0x41 ; 65 bbe: 8a 31 cpi r24, 0x1A ; 26 bc0: 28 f4 brcc .+10 ; 0xbcc code = pgm_read_byte(&morse[c-'A'+10]); // Same as above bc2: e2 2f mov r30, r18 bc4: f0 e0 ldi r31, 0x00 ; 0 bc6: e8 5b subi r30, 0xB8 ; 184 bc8: ff 4f sbci r31, 0xFF ; 255 bca: 14 91 lpm r17, Z+ bcc: 80 e0 ldi r24, 0x00 ; 0 bce: 90 e0 ldi r25, 0x00 ; 0 // Last we need to handle special characters. There is a small char // array "spechar" which contains the characters for the morse elements // at the end of the "morse" array (see there!) for(i=0;i code = pgm_read_byte(&morse[i+36]); // Map it to morse code bdc: fc 01 movw r30, r24 bde: ed 55 subi r30, 0x5D ; 93 be0: ff 4f sbci r31, 0xFF ; 255 be2: 14 91 lpm r17, Z+ be4: 01 96 adiw r24, 0x01 ; 1 code = pgm_read_byte(&morse[c-'A'+10]); // Same as above // Last we need to handle special characters. There is a small char // array "spechar" which contains the characters for the morse elements // at the end of the "morse" array (see there!) for(i=0;i if (c == pgm_read_byte(&spechar[i])) // Does it contain our character code = pgm_read_byte(&morse[i+36]); // Map it to morse code if(c==' ') // Do they want us to transmit a space (a gap of 7 dots) bec: 20 32 cpi r18, 0x20 ; 32 bee: 81 f4 brne .+32 ; 0xc10 yackdelay(IWGLEN-ICGLEN); // ICG was already played after previous char bf0: 84 e0 ldi r24, 0x04 ; 4 bf2: a4 dd rcall .-1208 ; 0x73c bf4: 12 c0 rjmp .+36 ; 0xc1a else { while (code != 0x80) // Stop when EOC bit has reached MSB { if (yackctrlkey(FALSE)) // Stop playing if someone pushes key bf6: 80 e0 ldi r24, 0x00 ; 0 bf8: 96 df rcall .-212 ; 0xb26 bfa: 88 23 and r24, r24 bfc: 71 f4 brne .+28 ; 0xc1a return; if (code & 0x80) // MSB set ? bfe: 17 ff sbrs r17, 7 c00: 02 c0 rjmp .+4 ; 0xc06 yackplay(DAH); // ..then play a dash c02: 82 e0 ldi r24, 0x02 ; 2 c04: 01 c0 rjmp .+2 ; 0xc08 else // MSB cleared ? yackplay(DIT); // .. then play a dot c06: 81 e0 ldi r24, 0x01 ; 1 c08: bb dd rcall .-1162 ; 0x780 yackdelay(IEGLEN); // Inter Element gap c0a: 81 e0 ldi r24, 0x01 ; 1 c0c: 97 dd rcall .-1234 ; 0x73c code = code << 1; // Shift code on position left (to next element) c0e: 11 0f add r17, r17 if(c==' ') // Do they want us to transmit a space (a gap of 7 dots) yackdelay(IWGLEN-ICGLEN); // ICG was already played after previous char else { while (code != 0x80) // Stop when EOC bit has reached MSB c10: 10 38 cpi r17, 0x80 ; 128 c12: 89 f7 brne .-30 ; 0xbf6 yackdelay(IEGLEN); // Inter Element gap code = code << 1; // Shift code on position left (to next element) } yackdelay(ICGLEN - IEGLEN); // IEG was already played after element c14: 82 e0 ldi r24, 0x02 ; 2 c16: 92 dd rcall .-1244 ; 0x73c yackfarns(); // Insert another gap for farnsworth keying c18: a4 dd rcall .-1208 ; 0x762 } } c1a: 1f 91 pop r17 c1c: 08 95 ret 00000c1e : @param function RECORD or PLAY @param msgnr 1 or 2 or 3 or 4 @return TRUE if all OK, FALSE if lock prevented message recording */ { c1e: cf 92 push r12 c20: df 92 push r13 c22: ef 92 push r14 c24: ff 92 push r15 c26: 0f 93 push r16 c28: 1f 93 push r17 c2a: df 93 push r29 c2c: cf 93 push r28 c2e: cd b7 in r28, 0x3d ; 61 c30: de b7 in r29, 0x3e ; 62 c32: c4 56 subi r28, 0x64 ; 100 c34: d0 40 sbci r29, 0x00 ; 0 c36: 0f b6 in r0, 0x3f ; 63 c38: f8 94 cli c3a: de bf out 0x3e, r29 ; 62 c3c: 0f be out 0x3f, r0 ; 63 c3e: cd bf out 0x3d, r28 ; 61 c40: 06 2f mov r16, r22 word extimer = 0; // Detects end of message (10 sec) byte i = 0; // Pointer into RAM buffer byte n; // Generic counter if (function == RECORD) c42: 81 30 cpi r24, 0x01 ; 1 c44: 09 f0 breq .+2 ; 0xc48 c46: 4e c0 rjmp .+156 ; 0xce4 c48: 68 ee ldi r22, 0xE8 ; 232 c4a: e6 2e mov r14, r22 c4c: 63 e0 ldi r22, 0x03 ; 3 c4e: f6 2e mov r15, r22 c50: 10 e0 ldi r17, 0x00 ; 0 { if (yackctrlkey(TRUE)) return; if ((c = yackiambic(ON))) // Check for a character from the key { rambuffer[i++] = c; // Add that character to our buffer c52: 6e 01 movw r12, r28 c54: 08 94 sec c56: c1 1c adc r12, r1 c58: d1 1c adc r13, r1 { extimer = YACKSECS(DEFTIMEOUT); // 5 Second until message end while(extimer--) // Continue until we waited 10 seconds { if (yackctrlkey(TRUE)) return; c5a: 81 e0 ldi r24, 0x01 ; 1 c5c: 64 df rcall .-312 ; 0xb26 c5e: 88 23 and r24, r24 c60: 09 f0 breq .+2 ; 0xc64 c62: 73 c0 rjmp .+230 ; 0xd4a if ((c = yackiambic(ON))) // Check for a character from the key c64: 81 e0 ldi r24, 0x01 ; 1 c66: 05 de rcall .-1014 ; 0x872 c68: 88 23 and r24, r24 c6a: 21 f4 brne .+8 ; 0xc74 if (function == RECORD) { extimer = YACKSECS(DEFTIMEOUT); // 5 Second until message end while(extimer--) // Continue until we waited 10 seconds c6c: 08 94 sec c6e: e1 08 sbc r14, r1 c70: f1 08 sbc r15, r1 c72: 09 c0 rjmp .+18 ; 0xc86 { if (yackctrlkey(TRUE)) return; if ((c = yackiambic(ON))) // Check for a character from the key { rambuffer[i++] = c; // Add that character to our buffer c74: f6 01 movw r30, r12 c76: e1 0f add r30, r17 c78: f1 1d adc r31, r1 c7a: 80 83 st Z, r24 c7c: 1f 5f subi r17, 0xFF ; 255 c7e: 58 ee ldi r21, 0xE8 ; 232 c80: e5 2e mov r14, r21 c82: 53 e0 ldi r21, 0x03 ; 3 c84: f5 2e mov r15, r21 extimer = YACKSECS(DEFTIMEOUT); // Reset End of message timer } if (i>=RBSIZE) // End of buffer reached? c86: 14 36 cpi r17, 0x64 ; 100 c88: 10 f0 brcs .+4 ; 0xc8e { yackerror(); c8a: 8c dd rcall .-1256 ; 0x7a4 c8c: 10 e0 ldi r17, 0x00 ; 0 using an interrupt or a timer. For simpler cases this is a busy wait routine that delays exactly YACKBEAT ms. */ { while((TIFR & (1< TIFR |= (1< yackbeat(); // 10 ms heartbeat } // Extimer has expired. Message has ended if(i) // Was anything received at all? ca0: 11 23 and r17, r17 ca2: f1 f0 breq .+60 ; 0xce0 { rambuffer[--i] = 0; // Add a \0 end marker over last space ca4: 11 50 subi r17, 0x01 ; 1 ca6: ce 01 movw r24, r28 ca8: 01 96 adiw r24, 0x01 ; 1 caa: fc 01 movw r30, r24 cac: e1 0f add r30, r17 cae: f1 1d adc r31, r1 cb0: 10 82 st Z, r1 // if (yackctrlkey(TRUE)) {return;} //Break to command mode without saving if command key pressed // yackchar(rambuffer[n]); // } // Store it in EEPROM if (msgnr == 1) cb2: 01 30 cpi r16, 0x01 ; 1 cb4: 19 f4 brne .+6 ; 0xcbc eeprom_write_block(rambuffer,eebuffer1,RBSIZE); cb6: 6a e0 ldi r22, 0x0A ; 10 cb8: 70 e0 ldi r23, 0x00 ; 0 cba: 04 c0 rjmp .+8 ; 0xcc4 if (msgnr == 2) cbc: 02 30 cpi r16, 0x02 ; 2 cbe: 31 f4 brne .+12 ; 0xccc eeprom_write_block(rambuffer,eebuffer2,RBSIZE); cc0: 6e e6 ldi r22, 0x6E ; 110 cc2: 70 e0 ldi r23, 0x00 ; 0 cc4: 44 e6 ldi r20, 0x64 ; 100 cc6: 50 e0 ldi r21, 0x00 ; 0 cc8: 6f d1 rcall .+734 ; 0xfa8 <__eewr_block_tn85> cca: 3f c0 rjmp .+126 ; 0xd4a if (msgnr == 3) ccc: 03 30 cpi r16, 0x03 ; 3 cce: 19 f4 brne .+6 ; 0xcd6 eeprom_write_block(rambuffer,eebuffer3,RBSIZE); cd0: 62 ed ldi r22, 0xD2 ; 210 cd2: 70 e0 ldi r23, 0x00 ; 0 cd4: f7 cf rjmp .-18 ; 0xcc4 if (msgnr == 4) cd6: 04 30 cpi r16, 0x04 ; 4 cd8: c1 f5 brne .+112 ; 0xd4a eeprom_write_block(rambuffer,eebuffer4,RBSIZE); cda: 66 e3 ldi r22, 0x36 ; 54 cdc: 71 e0 ldi r23, 0x01 ; 1 cde: f2 cf rjmp .-28 ; 0xcc4 } else yackerror(); ce0: 61 dd rcall .-1342 ; 0x7a4 ce2: 33 c0 rjmp .+102 ; 0xd4a } if (function == PLAY) ce4: 82 30 cpi r24, 0x02 ; 2 ce6: 89 f5 brne .+98 ; 0xd4a { // Retrieve the message from EEPROM if (msgnr == 1) ce8: 61 30 cpi r22, 0x01 ; 1 cea: 29 f4 brne .+10 ; 0xcf6 eeprom_read_block(rambuffer,eebuffer1,RBSIZE); cec: ce 01 movw r24, r28 cee: 01 96 adiw r24, 0x01 ; 1 cf0: 6a e0 ldi r22, 0x0A ; 10 cf2: 70 e0 ldi r23, 0x00 ; 0 cf4: 14 c0 rjmp .+40 ; 0xd1e if (msgnr == 2) cf6: 62 30 cpi r22, 0x02 ; 2 cf8: 29 f4 brne .+10 ; 0xd04 eeprom_read_block(rambuffer,eebuffer2,RBSIZE); cfa: ce 01 movw r24, r28 cfc: 01 96 adiw r24, 0x01 ; 1 cfe: 6e e6 ldi r22, 0x6E ; 110 d00: 70 e0 ldi r23, 0x00 ; 0 d02: 0d c0 rjmp .+26 ; 0xd1e if (msgnr == 3) d04: 63 30 cpi r22, 0x03 ; 3 d06: 29 f4 brne .+10 ; 0xd12 eeprom_read_block(rambuffer,eebuffer3,RBSIZE); d08: ce 01 movw r24, r28 d0a: 01 96 adiw r24, 0x01 ; 1 d0c: 62 ed ldi r22, 0xD2 ; 210 d0e: 70 e0 ldi r23, 0x00 ; 0 d10: 06 c0 rjmp .+12 ; 0xd1e if (msgnr == 4) d12: 64 30 cpi r22, 0x04 ; 4 d14: 39 f4 brne .+14 ; 0xd24 eeprom_read_block(rambuffer,eebuffer4,RBSIZE); d16: ce 01 movw r24, r28 d18: 01 96 adiw r24, 0x01 ; 1 d1a: 66 e3 ldi r22, 0x36 ; 54 d1c: 71 e0 ldi r23, 0x01 ; 1 d1e: 44 e6 ldi r20, 0x64 ; 100 d20: 50 e0 ldi r21, 0x00 ; 0 d22: 25 d1 rcall .+586 ; 0xf6e <__eerd_block_tn85> d24: 10 e0 ldi r17, 0x00 ; 0 // Replay the message for (n=0;(c=rambuffer[n]);n++){ // Read until end of message d26: 7e 01 movw r14, r28 d28: 08 94 sec d2a: e1 1c adc r14, r1 d2c: f1 1c adc r15, r1 d2e: 07 c0 rjmp .+14 ; 0xd3e if (yackctrlkey(FALSE)) {return;} //Break immediately if command key pressed d30: 80 e0 ldi r24, 0x00 ; 0 d32: f9 de rcall .-526 ; 0xb26 d34: 88 23 and r24, r24 d36: 49 f4 brne .+18 ; 0xd4a yackchar(c); // play it back d38: 80 2f mov r24, r16 d3a: 2a df rcall .-428 ; 0xb90 eeprom_read_block(rambuffer,eebuffer3,RBSIZE); if (msgnr == 4) eeprom_read_block(rambuffer,eebuffer4,RBSIZE); // Replay the message for (n=0;(c=rambuffer[n]);n++){ // Read until end of message d3c: 1f 5f subi r17, 0xFF ; 255 d3e: f7 01 movw r30, r14 d40: e1 0f add r30, r17 d42: f1 1d adc r31, r1 d44: 00 81 ld r16, Z d46: 00 23 and r16, r16 d48: 99 f7 brne .-26 ; 0xd30 yackchar(c); // play it back } } } d4a: cc 59 subi r28, 0x9C ; 156 d4c: df 4f sbci r29, 0xFF ; 255 d4e: 0f b6 in r0, 0x3f ; 63 d50: f8 94 cli d52: de bf out 0x3e, r29 ; 62 d54: 0f be out 0x3f, r0 ; 63 d56: cd bf out 0x3d, r28 ; 61 d58: cf 91 pop r28 d5a: df 91 pop r29 d5c: 1f 91 pop r17 d5e: 0f 91 pop r16 d60: ff 90 pop r15 d62: ef 90 pop r14 d64: df 90 pop r13 d66: cf 90 pop r12 d68: 08 95 ret 00000d6a : @param n The number to send */ { d6a: ef 92 push r14 d6c: ff 92 push r15 d6e: 1f 93 push r17 d70: df 93 push r29 d72: cf 93 push r28 d74: 00 d0 rcall .+0 ; 0xd76 d76: 00 d0 rcall .+0 ; 0xd78 d78: 0f 92 push r0 d7a: cd b7 in r28, 0x3d ; 61 d7c: de b7 in r29, 0x3e ; 62 d7e: 9c 01 movw r18, r24 d80: 10 e0 ldi r17, 0x00 ; 0 char buffer[5]; byte i = 0; while (n) // Until nothing left or control key pressed { buffer[i++] = n%10+'0'; // Store rest of division by 10 d82: 7e 01 movw r14, r28 d84: 08 94 sec d86: e1 1c adc r14, r1 d88: f1 1c adc r15, r1 d8a: 0f c0 rjmp .+30 ; 0xdaa d8c: f7 01 movw r30, r14 d8e: e1 0f add r30, r17 d90: f1 1d adc r31, r1 d92: c9 01 movw r24, r18 d94: 6a e0 ldi r22, 0x0A ; 10 d96: 70 e0 ldi r23, 0x00 ; 0 d98: c3 d0 rcall .+390 ; 0xf20 <__udivmodhi4> d9a: 80 5d subi r24, 0xD0 ; 208 d9c: 80 83 st Z, r24 d9e: 1f 5f subi r17, 0xFF ; 255 n /= 10; // Divide by 10 da0: c9 01 movw r24, r18 da2: 6a e0 ldi r22, 0x0A ; 10 da4: 70 e0 ldi r23, 0x00 ; 0 da6: bc d0 rcall .+376 ; 0xf20 <__udivmodhi4> da8: 9b 01 movw r18, r22 { char buffer[5]; byte i = 0; while (n) // Until nothing left or control key pressed daa: 21 15 cp r18, r1 dac: 31 05 cpc r19, r1 dae: 71 f7 brne .-36 ; 0xd8c db0: 0b c0 rjmp .+22 ; 0xdc8 n /= 10; // Divide by 10 } while (i) { if (yackctrlkey(TRUE)) {break;} db2: 81 e0 ldi r24, 0x01 ; 1 db4: b8 de rcall .-656 ; 0xb26 db6: 88 23 and r24, r24 db8: 69 f4 brne .+26 ; 0xdd4 yackchar(buffer[--i]); dba: 11 50 subi r17, 0x01 ; 1 dbc: f7 01 movw r30, r14 dbe: e1 0f add r30, r17 dc0: f1 1d adc r31, r1 dc2: 80 81 ld r24, Z dc4: e5 de rcall .-566 ; 0xb90 dc6: 04 c0 rjmp .+8 ; 0xdd0 dc8: 7e 01 movw r14, r28 dca: 08 94 sec dcc: e1 1c adc r14, r1 dce: f1 1c adc r15, r1 { buffer[i++] = n%10+'0'; // Store rest of division by 10 n /= 10; // Divide by 10 } while (i) dd0: 11 23 and r17, r17 dd2: 79 f7 brne .-34 ; 0xdb2 { if (yackctrlkey(TRUE)) {break;} yackchar(buffer[--i]); } yackchar (' '); dd4: 80 e2 ldi r24, 0x20 ; 32 dd6: dc de rcall .-584 ; 0xb90 } dd8: 0f 90 pop r0 dda: 0f 90 pop r0 ddc: 0f 90 pop r0 dde: 0f 90 pop r0 de0: 0f 90 pop r0 de2: cf 91 pop r28 de4: df 91 pop r29 de6: 1f 91 pop r17 de8: ff 90 pop r15 dea: ef 90 pop r14 dec: 08 95 ret 00000dee : and/or sidetone depending on feature bit settings. @param p Pointer to string location in FLASH */ { dee: 1f 93 push r17 df0: cf 93 push r28 df2: df 93 push r29 df4: ec 01 movw r28, r24 df6: 02 c0 rjmp .+4 ; 0xdfc char c; while ((c = pgm_read_byte(p++))&& !(yackctrlkey(TRUE)) ) // While end of string in flash not reached and ctrl not pressed yackchar(c); // Play the read character df8: 81 2f mov r24, r17 dfa: ca de rcall .-620 ; 0xb90 dfc: fe 01 movw r30, r28 */ { char c; while ((c = pgm_read_byte(p++))&& !(yackctrlkey(TRUE)) ) dfe: 21 96 adiw r28, 0x01 ; 1 e00: 14 91 lpm r17, Z+ e02: 11 23 and r17, r17 e04: 21 f0 breq .+8 ; 0xe0e e06: 81 e0 ldi r24, 0x01 ; 1 e08: 8e de rcall .-740 ; 0xb26 e0a: 88 23 and r24, r24 e0c: a9 f3 breq .-22 ; 0xdf8 // While end of string in flash not reached and ctrl not pressed yackchar(c); // Play the read character // abort now if someone presses command key } e0e: df 91 pop r29 e10: cf 91 pop r28 e12: 1f 91 pop r17 e14: 08 95 ret 00000e16 : This produces a solid keydown for TUNEDURATION seconds. After this the TX is unkeyed. The same can be achieved by presing either the DIT or the DAH contact or the control key. */ { e16: cf 93 push r28 e18: df 93 push r29 word timer = YACKSECS(TUNEDURATION); key(DOWN); e1a: 82 e0 ldi r24, 0x02 ; 2 e1c: 52 dc rcall .-1884 ; 0x6c2 e1e: c0 ea ldi r28, 0xA0 ; 160 e20: df e0 ldi r29, 0x0F ; 15 e22: 09 c0 rjmp .+18 ; 0xe36 while(timer && (KEYINP & (1< TIFR |= (1< e36: b3 9b sbis 0x16, 3 ; 22 e38: 06 c0 rjmp .+12 ; 0xe46 e3a: b4 9b sbis 0x16, 4 ; 22 e3c: 04 c0 rjmp .+8 ; 0xe46 e3e: 81 e0 ldi r24, 0x01 ; 1 e40: 72 de rcall .-796 ; 0xb26 e42: 88 23 and r24, r24 e44: 79 f3 breq .-34 ; 0xe24 { timer--; yackbeat(); } key(UP); e46: 81 e0 ldi r24, 0x01 ; 1 e48: 3c dc rcall .-1928 ; 0x6c2 } e4a: df 91 pop r29 e4c: cf 91 pop r28 e4e: 08 95 ret 00000e50 : stored in the .h file. It sets the dirty flag and calls the save routine to write the data into EEPROM immediately. */ { ctcvalue=DEFCTC; // Initialize to 800 Hz e50: 8d e4 ldi r24, 0x4D ; 77 e52: 90 e0 ldi r25, 0x00 ; 0 e54: 90 93 75 00 sts 0x0075, r25 e58: 80 93 74 00 sts 0x0074, r24 wpm=DEFWPM; // Init to default speed e5c: 8f e0 ldi r24, 0x0F ; 15 e5e: 80 93 78 00 sts 0x0078, r24 wpmcnt=(1200/YACKBEAT)/DEFWPM; // default speed e62: 80 e1 ldi r24, 0x10 ; 16 e64: 90 e0 ldi r25, 0x00 ; 0 e66: 90 93 77 00 sts 0x0077, r25 e6a: 80 93 76 00 sts 0x0076, r24 farnsworth=0; // No Farnsworth gap e6e: 10 92 79 00 sts 0x0079, r1 yackflags = FLAGDEFAULT; e72: 84 e3 ldi r24, 0x34 ; 52 e74: 80 93 73 00 sts 0x0073, r24 volflags |= DIRTYFLAG; e78: 80 91 66 00 lds r24, 0x0066 e7c: 84 60 ori r24, 0x04 ; 4 e7e: 80 93 66 00 sts 0x0066, r24 yacksave(); // Store them in EEPROM e82: 2d de rcall .-934 ; 0xade } e84: 08 95 ret 00000e86 : { byte magval; // Configure DDR. Make OUT and ST output ports SETBIT (OUTDDR,OUTPIN); e86: b8 9a sbi 0x17, 0 ; 23 SETBIT (STDDR,STPIN); e88: b9 9a sbi 0x17, 1 ; 23 // Raise internal pullups for all inputs SETBIT (KEYPORT,DITPIN); e8a: c3 9a sbi 0x18, 3 ; 24 SETBIT (KEYPORT,DAHPIN); e8c: c4 9a sbi 0x18, 4 ; 24 SETBIT (BTNPORT,BTNPIN); e8e: c2 9a sbi 0x18, 2 ; 24 magval = eeprom_read_byte(&magic); // Retrieve magic value e90: 80 e0 ldi r24, 0x00 ; 0 e92: 90 e0 ldi r25, 0x00 ; 0 e94: 7c d0 rcall .+248 ; 0xf8e <__eerd_byte_tn85> if (magval == MAGPAT) // Is memory valid e96: 85 3a cpi r24, 0xA5 ; 165 e98: 01 f5 brne .+64 ; 0xeda { ctcvalue = eeprom_read_word(&ctcstor); // Retrieve last ctc setting e9a: 82 e0 ldi r24, 0x02 ; 2 e9c: 90 e0 ldi r25, 0x00 ; 0 e9e: 7f d0 rcall .+254 ; 0xf9e <__eerd_word_tn85> ea0: 90 93 75 00 sts 0x0075, r25 ea4: 80 93 74 00 sts 0x0074, r24 wpm = eeprom_read_byte(&wpmstor); // Retrieve last wpm setting ea8: 84 e0 ldi r24, 0x04 ; 4 eaa: 90 e0 ldi r25, 0x00 ; 0 eac: 70 d0 rcall .+224 ; 0xf8e <__eerd_byte_tn85> eae: 68 2f mov r22, r24 eb0: 80 93 78 00 sts 0x0078, r24 wpmcnt=(1200/YACKBEAT)/wpm; // Calculate speed eb4: 80 ef ldi r24, 0xF0 ; 240 eb6: 90 e0 ldi r25, 0x00 ; 0 eb8: 70 e0 ldi r23, 0x00 ; 0 eba: 46 d0 rcall .+140 ; 0xf48 <__divmodhi4> ebc: 70 93 77 00 sts 0x0077, r23 ec0: 60 93 76 00 sts 0x0076, r22 farnsworth = eeprom_read_byte(&fwstor); // Retrieve last wpm setting ec4: 85 e0 ldi r24, 0x05 ; 5 ec6: 90 e0 ldi r25, 0x00 ; 0 ec8: 62 d0 rcall .+196 ; 0xf8e <__eerd_byte_tn85> eca: 80 93 79 00 sts 0x0079, r24 yackflags = eeprom_read_byte(&flagstor); // Retrieve last flags ece: 81 e0 ldi r24, 0x01 ; 1 ed0: 90 e0 ldi r25, 0x00 ; 0 ed2: 5d d0 rcall .+186 ; 0xf8e <__eerd_byte_tn85> ed4: 80 93 73 00 sts 0x0073, r24 ed8: 01 c0 rjmp .+2 ; 0xedc } else { yackreset(); eda: ba df rcall .-140 ; 0xe50 } yackinhibit(OFF); edc: 80 e0 ldi r24, 0x00 ; 0 ede: 1b dc rcall .-1994 ; 0x716 #ifdef POWERSAVE PCMSK |= PWRWAKE; // Define which keys wake us up ee0: 85 b3 in r24, 0x15 ; 21 ee2: 8c 61 ori r24, 0x1C ; 28 ee4: 85 bb out 0x15, r24 ; 21 GIMSK |= (1<: efc: 55 27 eor r21, r21 efe: 00 24 eor r0, r0 00000f00 <__mulhi3_loop>: f00: 80 ff sbrs r24, 0 f02: 02 c0 rjmp .+4 ; 0xf08 <__mulhi3_skip1> f04: 06 0e add r0, r22 f06: 57 1f adc r21, r23 00000f08 <__mulhi3_skip1>: f08: 66 0f add r22, r22 f0a: 77 1f adc r23, r23 f0c: 61 15 cp r22, r1 f0e: 71 05 cpc r23, r1 f10: 21 f0 breq .+8 ; 0xf1a <__mulhi3_exit> f12: 96 95 lsr r25 f14: 87 95 ror r24 f16: 00 97 sbiw r24, 0x00 ; 0 f18: 99 f7 brne .-26 ; 0xf00 <__mulhi3_loop> 00000f1a <__mulhi3_exit>: f1a: 95 2f mov r25, r21 f1c: 80 2d mov r24, r0 f1e: 08 95 ret 00000f20 <__udivmodhi4>: f20: aa 1b sub r26, r26 f22: bb 1b sub r27, r27 f24: 51 e1 ldi r21, 0x11 ; 17 f26: 07 c0 rjmp .+14 ; 0xf36 <__udivmodhi4_ep> 00000f28 <__udivmodhi4_loop>: f28: aa 1f adc r26, r26 f2a: bb 1f adc r27, r27 f2c: a6 17 cp r26, r22 f2e: b7 07 cpc r27, r23 f30: 10 f0 brcs .+4 ; 0xf36 <__udivmodhi4_ep> f32: a6 1b sub r26, r22 f34: b7 0b sbc r27, r23 00000f36 <__udivmodhi4_ep>: f36: 88 1f adc r24, r24 f38: 99 1f adc r25, r25 f3a: 5a 95 dec r21 f3c: a9 f7 brne .-22 ; 0xf28 <__udivmodhi4_loop> f3e: 80 95 com r24 f40: 90 95 com r25 f42: bc 01 movw r22, r24 f44: cd 01 movw r24, r26 f46: 08 95 ret 00000f48 <__divmodhi4>: f48: 97 fb bst r25, 7 f4a: 09 2e mov r0, r25 f4c: 07 26 eor r0, r23 f4e: 0a d0 rcall .+20 ; 0xf64 <__divmodhi4_neg1> f50: 77 fd sbrc r23, 7 f52: 04 d0 rcall .+8 ; 0xf5c <__divmodhi4_neg2> f54: e5 df rcall .-54 ; 0xf20 <__udivmodhi4> f56: 06 d0 rcall .+12 ; 0xf64 <__divmodhi4_neg1> f58: 00 20 and r0, r0 f5a: 1a f4 brpl .+6 ; 0xf62 <__divmodhi4_exit> 00000f5c <__divmodhi4_neg2>: f5c: 70 95 com r23 f5e: 61 95 neg r22 f60: 7f 4f sbci r23, 0xFF ; 255 00000f62 <__divmodhi4_exit>: f62: 08 95 ret 00000f64 <__divmodhi4_neg1>: f64: f6 f7 brtc .-4 ; 0xf62 <__divmodhi4_exit> f66: 90 95 com r25 f68: 81 95 neg r24 f6a: 9f 4f sbci r25, 0xFF ; 255 f6c: 08 95 ret 00000f6e <__eerd_block_tn85>: f6e: dc 01 movw r26, r24 f70: cb 01 movw r24, r22 00000f72 <__eerd_blraw_tn85>: f72: fc 01 movw r30, r24 f74: e1 99 sbic 0x1c, 1 ; 28 f76: fe cf rjmp .-4 ; 0xf74 <__eerd_blraw_tn85+0x2> f78: 06 c0 rjmp .+12 ; 0xf86 <__eerd_blraw_tn85+0x14> f7a: ff bb out 0x1f, r31 ; 31 f7c: ee bb out 0x1e, r30 ; 30 f7e: e0 9a sbi 0x1c, 0 ; 28 f80: 31 96 adiw r30, 0x01 ; 1 f82: 0d b2 in r0, 0x1d ; 29 f84: 0d 92 st X+, r0 f86: 41 50 subi r20, 0x01 ; 1 f88: 50 40 sbci r21, 0x00 ; 0 f8a: b8 f7 brcc .-18 ; 0xf7a <__eerd_blraw_tn85+0x8> f8c: 08 95 ret 00000f8e <__eerd_byte_tn85>: f8e: e1 99 sbic 0x1c, 1 ; 28 f90: fe cf rjmp .-4 ; 0xf8e <__eerd_byte_tn85> f92: 9f bb out 0x1f, r25 ; 31 f94: 8e bb out 0x1e, r24 ; 30 f96: e0 9a sbi 0x1c, 0 ; 28 f98: 99 27 eor r25, r25 f9a: 8d b3 in r24, 0x1d ; 29 f9c: 08 95 ret 00000f9e <__eerd_word_tn85>: f9e: a8 e1 ldi r26, 0x18 ; 24 fa0: b0 e0 ldi r27, 0x00 ; 0 fa2: 42 e0 ldi r20, 0x02 ; 2 fa4: 50 e0 ldi r21, 0x00 ; 0 fa6: e5 cf rjmp .-54 ; 0xf72 <__eerd_blraw_tn85> 00000fa8 <__eewr_block_tn85>: fa8: dc 01 movw r26, r24 faa: cb 01 movw r24, r22 fac: 02 c0 rjmp .+4 ; 0xfb2 <__eewr_block_tn85+0xa> fae: 2d 91 ld r18, X+ fb0: 05 d0 rcall .+10 ; 0xfbc <__eewr_r18_tn85> fb2: 41 50 subi r20, 0x01 ; 1 fb4: 50 40 sbci r21, 0x00 ; 0 fb6: d8 f7 brcc .-10 ; 0xfae <__eewr_block_tn85+0x6> fb8: 08 95 ret 00000fba <__eewr_byte_tn85>: fba: 26 2f mov r18, r22 00000fbc <__eewr_r18_tn85>: fbc: e1 99 sbic 0x1c, 1 ; 28 fbe: fe cf rjmp .-4 ; 0xfbc <__eewr_r18_tn85> fc0: 1c ba out 0x1c, r1 ; 28 fc2: 9f bb out 0x1f, r25 ; 31 fc4: 8e bb out 0x1e, r24 ; 30 fc6: 2d bb out 0x1d, r18 ; 29 fc8: 0f b6 in r0, 0x3f ; 63 fca: f8 94 cli fcc: e2 9a sbi 0x1c, 2 ; 28 fce: e1 9a sbi 0x1c, 1 ; 28 fd0: 0f be out 0x3f, r0 ; 63 fd2: 01 96 adiw r24, 0x01 ; 1 fd4: 08 95 ret 00000fd6 <__eewr_word_tn85>: fd6: f1 df rcall .-30 ; 0xfba <__eewr_byte_tn85> fd8: 27 2f mov r18, r23 fda: f0 cf rjmp .-32 ; 0xfbc <__eewr_r18_tn85> 00000fdc <_exit>: fdc: f8 94 cli 00000fde <__stop_program>: fde: ff cf rjmp .-2 ; 0xfde <__stop_program>