2 # Converts morse.messages to *+morse.asm or morse+auto.inc.
3 # morse-auto.asm specifies some flash contents, as follows:
5 # Each message XY produces a symbol
7 # which is in the flash between morse_messages_start and
8 # morse_messages_end, and which is guaranteed to be aligned to a
11 # At that symbol will be a message in the following format:
12 # RAAAMMMM header byte, contents as follows:
13 # M (4 bits) number of bytes of morse pattern
14 # R reserved bit, always zero
15 # A (3 bits) number of bytes of addresses
16 # M bytes morse pattern, as bit string of LED on/off
17 # values (1=on) for equal-length periods
18 # (1 period = 1 morse dot), MS bit first
19 # trailing zeroes in last byte are probably
21 # A bytes zero or more addresses which should be read
22 # and the corresponding value shown in binary.
23 # Addresses are only one byte each, interpreted
24 # like an access bank reference.
26 # morse_messages_start and morse_messages_end should be defined in
27 # morse-defs.inc, and should also be 4-byte aligned. morse-defs.inc
28 # should also arrange to define any symbolic addresse referred to
29 # in morse-auto.messages, eg by including the pXXXX.inc.
31 # *+morse.asm contains the actual source and morse+auto.inc
32 # contains `equ' definitions for the addresses morse_XY.
39 " morse-generator <input>... asm\n".
40 " morse-generator <input>... [<file>.map] inc\n");
45 $includefile= 'morse-defs.inc';
46 if ($ARGV[$#ARGV] =~ s/^\-I//) {
47 $includefile= pop @ARGV;
51 $which eq 'asm' or $which eq 'inc' or badusage();
54 ($let,$morse) = (m/^([0-9A-Z])\s+([-.]+)$/) or die;
56 $morse =~ s/\-/1110/g;
61 sub oops ($) { die "morse-generator: $ARGV:$.: $_[0]\n"; }
63 $mapfile= $ARGV[$#ARGV];
65 if ($mapfile =~ m/\.map$/) {
67 $maph= new IO::File "$mapfile", 'r' or die "$0: $mapfile: $!\n";
69 next unless m/^\s+Symbols\s+$/ .. !/\S/;
71 next if m/^\s+Symbols\s+$/;
72 next if m/^\s+Name\s+Address\s+Location\s+Storage\s+File\s*$/;
73 next if m/^(?:\s+\-\-+){5}\s*$/;
74 m/^\s*([0-9a-zA-Z_]+)\s+(0+|0x[0-9a-f]+)\s+(program|data)\s+(static|extern)\s+(\S+)\s*$/
75 or die "$0: $mapfile:$.: cannot parse ?!\n";
76 ($sym,$val,$progdata,$staticext,$filename) = ($1,$2,$3,$4,$5);
77 next if $progdata ne 'data';
78 $filename =~ s/\.asm$//;
79 $sym= $staticext eq 'static' ? "$filename:$sym" : "::$sym";
82 die "$0: $mapfile: $!\n" if $maph->error;
87 print <<'END' or die $!
88 ; autogenerated - do not edit
98 morse_section org morse_messages_start
111 m/^([A-Z0-9]+)(\??)(?:\s+([^\t ;]+))?(?:\s+\;\s*(.*))?$/
112 or oops("syntax error");
115 @morse= split //, $morse_name;
116 @addrs= defined($3) ? split /\,/, $3 : ();
119 @addrs < 8 or oops("only up to 7 addrs are supported");
123 $morse= join '00000', map { $morse{$_} } @morse;
124 $morse .= '0' x 7; # padding to fill any partial byte
125 while ($morse =~ s/^([01]{8})//) {
128 $morse =~ m/^0{0,7}$/ or die;
129 $morse_bytes= scalar(@data);
131 unshift @data, sprintf "0x%x%x", scalar(@addrs), $morse_bytes;
133 s/^\:\b/ $filename.':' /e;
134 $filename= $1 if m/^([^:]+)\:/;
135 $_ = $symval{$_} if exists $symval{$_};
136 if ($which eq 'inc') {
139 printf STDERR "morse-generator: message \`%s': %s".
140 "unknown symbol \`%s'\n",
141 $morse_name, ($morse_optional ? 'warning: ' :''), $_;
142 exit 4 unless $morse_optional;
143 $val= ' xxx_unknown_xxx';
145 $val= "$_ - (0xf00 * !(($_ & 0xf00)^0xf00))";
150 push @data, ('0') x (3 - (scalar(@data) + 3) % 4);
152 print("morse_$morse_name db @data\n") or die $!
155 printf("morse_$morse_name equ morse_messages_start+0x%x\n",
159 $bytes += scalar @data;
162 print <<'END' or die $!
164 if $ > morse_messages_end
165 error "too much morse - extends beyond morse_messages_end"
172 STDIN->error and die $!;
173 STDOUT->error and die $!;