#
# morse_messages_start and morse_messages_end should be defined in
# morse-defs.inc, and should also be 4-byte aligned. morse-defs.inc
-# and morse-defs.fin should arrange to define any symbolic addresses
-# referred to in morse-auto.messages, by saying `extern' (in .fin) or
-# including the pXXXX.inc (in .inc).
+# should also arrange to define any symbolic addresse referred to
+# in morse-auto.messages, eg by including the pXXXX.inc.
#
# morse-auto.asm contains the actual source and morse-auto.inc
# contains `extern' references for the labels morse_XY.
+use IO::File;
use IO::Handle;
-sub badusage () { die "usage: morse-auto.asm-gen <input>... asm|inc\n"; }
+sub badusage () {
+ die ("usages:\n".
+ " morse-auto.asm-gen <input>... asm\n".
+ " morse-auto.asm-gen <input>... [<file>.map] inc\n");
+}
@ARGV or badusage();
$which= pop @ARGV;
sub oops ($) { die "morse-auto.asm-gen: $ARGV:$.: $_[0]\n"; }
+$mapfile= $ARGV[$#ARGV];
+
+if ($mapfile =~ m/\.map$/) {
+ pop @ARGV;
+ $maph= new IO::File "$mapfile", 'r' or die "$0: $mapfile: $!\n";
+ while (<$maph>) {
+ next unless m/^\s+Symbols\s+$/ .. !/\S/;
+ next unless m/\S/;
+ next if m/^\s+Symbols\s+$/;
+ next if m/^\s+Name\s+Address\s+Location\s+Storage\s+File\s*$/;
+ next if m/^(?:\s+\-\-+){5}\s*$/;
+ m/^\s*([0-9a-zA-Z_]+)\s+(0+|0x[0-9a-f]+)\s+(program|data)\s+(static|extern)\s+(\S+)\s*$/
+ or die "$0: $mapfile:$.: cannot parse ?!\n";
+ ($sym,$val,$progdata,$staticext,$filename) = ($1,$2,$3,$4,$5);
+ next if $progdata ne 'data';
+ $filename =~ s/\.asm$//;
+ $sym= "$filename:$sym" if $staticext eq 'static';
+ $symval{$sym}= $val;
+ }
+ die "$0: $mapfile: $!\n" if $maph->error;
+}
+
$"=',';
print <<'END' or die $!
if $which eq 'asm';
$bytes= 0;
+$.= 0;
while (<>) {
chomp;
$morse_bytes= scalar(@data);
unshift @data, sprintf "0x%x%x", scalar(@addrs), $morse_bytes;
-# push @data, @addrs;
push @data, map {
- "$_";
-# $_.'&0xff';
+ s/^\:/ $filename.':' /e;
+ $filename= $1 if m/^(.+)\:/;
+ (exists $symval{$_} ? $symval{$_} :
+ "$_ - (0xf00 * !(($_ & 0xf00)^0xf00))");
+
} @addrs;
push @data, ('0') x (3 - (scalar(@data) + 3) % 4);
error "too much morse - extends beyond morse_messages_end"
endif
- include morse-auto.fin
end
END
if $which eq 'asm';
;
; ;----------
; m_event_spong
-; bt_f_if0 i2c_st, st_something
+; bt_f_if0 st, st_something
; bra m_event_bad
; ;...
;
; m_event_several_including_spong
-; bs_f i2c_st, st_sponging
+; bs_f st, st_sponging
; bra metasyntacticing
;
; ;----------
udata_acs
-i2c_sspstat res 1
-i2c_sspcon1 res 1
-i2c_sspcon2 res 1 ; master only
-i2c_slave res 1 ; master only
+sspstat res 1
+sspcon1 res 1
+sspcon2 res 1 ; master only
+slave res 1 ; master only
-i2c_st res 1
+st res 1
-; i2c_st is a bitmask, bit set in visible states:
+; st is a bitmask, bit set in visible states:
; master slave
st_starting equ 7 ; Writing-Setup?,Reading-Busy?
st_addressing equ 6 ; Writing-Setup?,Reading-Busy?
return
; We have an interrupt:
- mov_ff SSPSTAT, i2c_sspstat
- mov_ff SSPCON1, i2c_sspcon1
- mov_ff SSPCON2, i2c_sspcon2
+ mov_ff SSPSTAT, sspstat
+ mov_ff SSPCON1, sspcon1
+ mov_ff SSPCON2, sspcon2
- bt_f_if1 i2c_sspcon1, WCOL
+ bt_f_if1 sspcon1, WCOL
bra_z m_event_bad
- bt_f_if1 i2c_sspcon1, SSPOV
+ bt_f_if1 sspcon1, SSPOV
bra_z m_event_bad
; No ? Well, then the I2C should be idle now:
- mov_fw i2c_sspcon2
+ mov_fw sspcon2
and_lw ~0x60 ; ACKSTAT,ACKDT
bra_nz m_event_bad
; OK...
- bt_f_if1 i2c_sspstat, R_W
+ bt_f_if1 sspstat, R_W
bra_nz m_event_bad
- bt_f_if1 i2c_st, st_stopping
+ bt_f_if1 st, st_stopping
bra m_event_done_stopping
- bt_f_if1 i2c_st, st_starting
+ bt_f_if1 st, st_starting
bra m_event_done_starting
; not just done SEN
- bt_f_if1 i2c_st, st_addressing
+ bt_f_if1 st, st_addressing
bra m_event_done_addressing
- bt_f_if1 i2c_st, st_writing
+ bt_f_if1 st, st_writing
bra m_event_done_writing
- bt_f_if1 i2c_st, st_acking
+ bt_f_if1 st, st_acking
bra m_event_done_acking
- bt_f_if1 i2c_st, st_reading
+ bt_f_if1 st, st_reading
bra m_event_done_reading
m_event_bad
;----------
m_start
-; i2c_st checked for busyness correct
+; st checked for busyness correct
; st_reading/writing set unchanged
; st_starting clear set
; W slave number any
-; i2c_slave any slave_number
+; slave any slave_number
; expects to return directly to main program (caller)
- mov_wf i2c_slave
+ mov_wf slave
and_lw 31
bra_nz m_improper_slave
- bs_f i2c_st, st_starting
+ bs_f st, st_starting
bs_f SSPCON2, SEN
return
;----------
m_event_done_starting
- mov_fw i2c_slave
+ mov_fw slave
rcall slave2addr
- bt_f_if1 i2c_st, st_reading
+ bt_f_if1 st, st_reading
bs_w 0 ; address bottom bit means read
mov_wf SSPBUF
- bc_f i2c_st, st_starting
- bs_f i2c_st, st_addressing
+ bc_f st, st_starting
+ bs_f st, st_addressing
return
;----------
m_event_done_addressing
- bt_f_if1 i2c_sspcon2, ACKSTAT
+ bt_f_if1 sspcon2, ACKSTAT
bra m_bad_address_ack
; OK, we got ack.
- bc_f i2c_st, st_addressing
- bt_f_if1 i2c_st, st_reading
+ bc_f st, st_addressing
+ bt_f_if1 st, st_reading
bra m_event_done_addressing_read
bra m_event_done_addressing_write
; st_stopping clear set
; st_reading/acking/writing any unchanged
; expects to return directly to main program or to end interrupt handler
- bs_f i2c_st, st_stopping
+ bs_f st, st_stopping
bs_f SSPCON2, PEN
return
;----------
m_event_done_stopping
- clr_f i2c_st
+ clr_f st
goto i2cmu_done
;----------
;----------
m_improper_slave
-; i2c_slave slave number
+; slave slave number
panic morse_SN
;========================================
; At call On return
; State Idle Writing-Setup
; W slave number any
- tst_f_ifnz i2c_st
+ tst_f_ifnz st
bra m_improper_write_start
- bs_f i2c_st, st_writing
+ bs_f st, st_writing
bra m_start
;----------
m_event_done_writing
; Did slave ack our byte ? It had better have done !
- bt_f_if1 i2c_sspcon2, ACKSTAT
+ bt_f_if1 sspcon2, ACKSTAT
bra m_event_bad
- bs_f i2c_st, st_subsequent
+ bs_f st, st_subsequent
;...
m_event_done_addressing_write
;----------
m_event_write_mustfinish
- bt_f_if0 i2c_st, st_subsequent
+ bt_f_if0 st, st_subsequent
bra m_improper_write_finish
bra m_stop
; At call On return
; State Idle Reading-Busy
; W slave number any
- tst_f_ifnz i2c_st
+ tst_f_ifnz st
bra m_improper_read_start
- bs_f i2c_st, st_reading
+ bs_f st, st_reading
bra m_start
;----------
;----------
m_event_done_reading
- bt_f_if0 i2c_sspstat, BF
+ bt_f_if0 sspstat, BF
bra m_event_bad
mov_fw SSPBUF
- bs_f i2c_st, st_awaiting
+ bs_f st, st_awaiting
goto i2cmu_read_got_byte
;----------
i2cm_read_another
; State Reading-Wait Reading-Busy
- bt_f_if0 i2c_st, st_awaiting
+ bt_f_if0 st, st_awaiting
bra m_improper_read_another
; OK, we're fine to read another:
;...
; st_awaiting still set cleared
; st_acking clear set
; expects to return directly to main program or to end interrupt handler
- bc_f i2c_st, st_awaiting
- bs_f i2c_st, st_acking
+ bc_f st, st_awaiting
+ bs_f st, st_acking
bc_f SSPCON2, ACKDT ; ACKDT=0 means to acknowledge
bs_f SSPCON2, ACKEN
return
;----------
i2cm_read_done
; State Reading-Wait Stopping
- bc_f i2c_st, st_reading
+ bc_f st, st_reading
- bt_f_if0 i2c_st, st_awaiting
+ bt_f_if0 st, st_awaiting
bra m_improper_read_done
; OK:
;----------
m_event_done_acking
- bc_f i2c_st, st_acking
+ bc_f st, st_acking
- bt_f_if1 i2c_st, st_reading
+ bt_f_if1 st, st_reading
bra m_event_done_acking_readmore
bra m_stop
; W slave number undefined
rcall slave2addr
mov_wf SSPADD
- clr_f i2c_st
+ clr_f st
mov_lw 0x16 ; !SSPEN, CKP(release), I2C 7-bit slave no-SP-int
mov_wf SSPCON1
mov_lw 0x01 ; !GCEN, SEN
; SSPIP any configured correctly
; GIEL 0 (disabled) 0 (disabled)
; ssp* shadows any all bits set
- set_f i2c_sspstat
- set_f i2c_sspcon1
- set_f i2c_sspcon2
+ set_f sspstat
+ set_f sspcon1
+ set_f sspcon2
bs_f TRISB, 0
bs_f TRISB, 1
bc_f IPR1, SSPIP
; Some macros:
chkvals_start_sspstat macro
- mov_fw i2c_sspstat
+ mov_fw sspstat
endm
chkval macro lastval, value, label
return
; We have an interrupt:
- bt_f_if1 i2c_sspcon1, WCOL
+ bt_f_if1 sspcon1, WCOL
bra_z s_event_bad
- bt_f_if1 i2c_sspcon1, SSPOV
+ bt_f_if1 sspcon1, SSPOV
bra_z s_event_bad
; Firstly, clear the interrupt flag so that if something else happens
; while we faff, the interrupt will be regenerated:
bc_f PIR1, SSPIF
- mov_ff SSPSTAT, i2c_sspstat
- mov_ff SSPCON1, i2c_sspcon1
+ mov_ff SSPSTAT, sspstat
+ mov_ff SSPCON1, sspcon1
- bt_f_if0 i2c_st, st_reading
+ bt_f_if0 st, st_reading
bra s_event_reading
- bt_f_if0 i2c_st, st_writing
+ bt_f_if0 st, st_writing
bra s_event_writing
s_event_idle
;----------
s_event_idle_addrrecvread
- bs_f i2c_st, st_reading
+ bs_f st, st_reading
call i2csu_read_begin
bra s_events_reading_datasend
chkval 0, 0xac, s_event_reading_datasent ; D,!P, S,R,!BF
; Whatever is happening, we're done reading now !
- clr_f i2c_st
+ clr_f st
call i2csu_read_done
chkvals_start_sspstat
;----------
s_event_idle_addrrecvwrite
bs_f SSPCON1, 3 ; we'll need the Stop interrupt
- bs_f i2c_st, st_writing
+ bs_f st, st_writing
; well, this is all fine so far, so do carry on:
s_write_slurpbyte
chkval 0, 0xa9, s_event_writing_datarecv ; D,!P, S,W,BF
; Well, we're done writing now in any case
- clr_f i2c_st
+ clr_f st
bc_f SSPCON1, 3 ; no Start and Stop interrupts any more
call i2csu_write_done
chkvals_addrrecv 0
; Then random junk:
- mov_fw i2c_sspstat
+ mov_fw sspstat
and_lw 0xc7 ; ?D_A, ?P; ?S
xor_lw 0x80 ; SMP, !CKE, !R_W, !UA, !BF
bt_f_if1 STATUS, Z
s_event_writing_datarecv
rcall s_write_slurpbyte
- bt_f_if1 i2c_st, st_subsequent
+ bt_f_if1 st, st_subsequent
goto i2csu_write_another
; not subsequent (yet):
- bs_f i2c_st, st_subsequent
+ bs_f st, st_subsequent
goto i2csu_write_begin
;======================================================================