TARGETS += $(foreach i, $(PICNOS), idlocs$i.hex noncode$i.hex)
 MORSE_INCLUDE ?= common.inc
 INCLUDES += ../iwjpictest/insn-aliases.inc morse+auto.inc
-MERGEHEX= $(CEBPIC)merge-hex $^ $o
 
 include ../common.make
 include ../pic.make
 
 idlocs*.asm
 morse+auto.inc
 ours-pindata.asm
+syncwrite.asm
 
 
 PROGRAMS=              test-sofar
 OBJS_test-sofar=       vectors.o panic.o routines-led.o i2clib.o       \
-                       misc.o slave.o detect.o variables.o
+                       misc.o slave.o detect.o variables.o             \
+                       syncwrite.o
 XCODEN_test-sofar=     morse
 XCODE1_test-sofar=     blank2 blank6
 
 
 include                $(CEBPIC)manypics.make
 
+syncwrite.asm: ../iwjpictest/syncwrite.asm
+               cp $< $@
+
 clean:         manypic-clean
 
- extern serial_write_char
-
  extern slave
 
  include vectors.fin
  include misc.fin
  include variables+vars.fin
  include detect.inc
+ include ../iwjpictest/syncwrite.inc
 
        end
 
 ;      set   clr   data? stop          start read? clr   full?
 ; (we don't usually mention SMP, CKE and UA below)
 
+; Labels of the form s_event_* are branches of the interrupt
+; handler and are supposed to finish with retfie_r.
+
 ; Some macros:
 
 chkvals_start macro what
                bra_nz  s_event_reading_not_another
                call    i2csu_read_another
                                ; 24cy until 1st insn of i2csu_read_another
+s_event_reading_datanack
                retfie_r
 
 ;...
                bra     improper_read_done_data
                bc_f    st, st_awaiting
                bs_f    st, st_reading
-s_event_reading_datanack
-               retfie_r
+               return
 
 ;========================================
 ; SLAVE - WRITING
                mov_fw  SSPSTAT
                and_lw  0xc7 ; ?D_A, ?P; ?S
                xor_lw  0x80 ; SMP, !CKE, !R_W, !UA, !BF
-               bt_f_if1 STATUS, Z
+               bra_nz  s_event_bad
                retfie_r
-               ; no good
-
-               bra     s_event_bad
 
 ;----------
 s_event_writing_datarecv
 
 ;      0       set buffer pointer to start, clear that byte
 ;      other   append char to buffer, clear byte at buffer pointer
 ;      
+;      $       toggle hex mode for reading
+;
 ;  Output characters:
 ;      SPC     i2cmu_done
 ;      other   i2cmu_read_got_byte
 
        udata_acs
 
-t      res     1
-ch     res     1
+t              res     1
+ch             res     1
+mode           res     1
+mode_readhex   equ     0
 
 delay_countfast                res     1
 delay_countmedium      res     1
 delay_countslow                res     1
 
+save_w         res     1
+save_status    res     1
+
        code
 
 ;----------
 
 ;----------
 master_interrupt_low
+       mov_ff  STATUS,save_status
+       mov_wf  save_w
+       ; we assume that none of the ISRs use BSR
        call    i2cm_interrupt
        call    serial_interrupt
-       retfie_r
+       mov_fw  save_w
+       mov_ff  save_status,STATUS
+       retfie
 
 ;----------
 master_interrupt_high
 ; FSR1 permanently points to start of buffer
 
 master
+       clr_f   mode
+
        call    serial_setup
        call    i2cm_init
        call    led_green
 i2cmu_done
        mov_lw  ' '
 i2cmu_read_got_byte
+       bt_f_if0 mode,mode_readhex
        bra     serial_write_char
+       bra     serial_write_hex
 
 ;----------
 i2cmu_write_next_byte
        rcall           serial_receive_reset
        return
 
-;----------------------------------------
-serial_write_char
-; W            character       undefined
-serial_write_char_loop
-       bt_f_if0        PIR1, TXIF
-       bra             serial_write_char_loop
-       mov_wf          TXREG
-       return
-
  include final.inc
 
        end
 
 
 PROGRAMS=      flasher copybits serialloop harness
 
-INCLUDES=      insn-aliases.inc  onecopybit.inc  test.inc  clockvaries.inc
+INCLUDES=      insn-aliases.inc  onecopybit.inc  test.inc  clockvaries.inc \
+               ../iwjpictest/syncwrite.inc
+
+CEBPIC=../cebpic/
 
 include ../common.make
 
 PROGRAM_HEXES= $(addsuffix .hex, $(PROGRAMS)) \
-               $(addsuffix -withcfg.hex, $(PROGRAMS))
+               $(addsuffix +withcfg.hex, $(PROGRAMS))
 
 all:           $(TARGETS) $(PROGRAM_HEXES)
 
 include ../pic.make
 
-%-withcfg.hex: %.o config.o $(LIBS) $(DEFLIBS)
-               $(LINK)
+%+withcfg.hex: %.hex config.hex
+               $(MERGEHEX)
 
 %.hex:         %.o $(LIBS) $(DEFLIBS)
                $(LINK)
 
+harness.hex:   harness.o syncwrite.o $(LIBS)
+               $(LINK)
+
 clean:         pic-clean
                rm -f $(INSN_TARGETS)
 
 
 sh             equ     FSR1H
 star_s         equ     INDF1
 
-perpicled_bit  equ     2
+ udata_acs
+ res 2 ; skip 0 and 1
+perpicled_bit  res 1
 
-e              equ     0x30
-t              equ     0x31
-b              equ     0x32
-f              equ     0x33
+sec_etbf udata_acs 0x30
+e              res 1
+t              res 1
+b              res 1
+f              res 1
 
-hex_temp       equ     0x38
-original_op    equ     0x39
-value_temp     equ     0x3a
+sec_temps udata_acs 0x38
+hex_temp       res 1
+original_op    res 1
+value_temp     res 1
 
 f_printset_bit equ     7
 
-test_loc_a5    equ     0x40
-test_loc_5a    equ     0x42
+sec_a5 udata_acs 0x40
+test_loc_a5    res 1
+
+sec_5a udata_acs 0x42
+test_loc_5a    res 1
+
+ code
 
 ;----------------------------------------
 serial_literal macro char
        rcall           serial_write_char
        endm
 
-       code
-
 start
        rcall           led_green
        rcall           serial_setup
        rcall           serial_receive_reset
        bra             serial_read_char_loop
 
-;----------------------------------------
-serial_write_char
-; W            character       undefined
-serial_write_char_loop
-       bt_f_if0        PIR1, TXIF
-       bra             serial_write_char_loop
-       mov_wf          TXREG
-       return
-
-;----------------------------------------
-serial_write_hex
-;      transmits W in hex through serial port
-;              Before          After
-; W            value           undefined
-; hex_temp     undefined       undefined
-       mov_wf          hex_temp
-       rcall           serial_write_hex_1digit_for_both
-       rcall           serial_write_hex_1digit_for_both
-       return
-
-;--------------------
-serial_write_hex_1digit_for_both
-;      transmits top nybble of hex_temp in hex
-;      through serial port, as above, and swaps nybbles
-;              Before          After
-; W            any             undefined
-; hex_temp     BBBBaaaa        aaaaBBBB        (BBBB was sent)
-       swap_f  hex_temp
-       mov_fw  hex_temp
-;...
-;--------------------
-serial_write_hex_digit
-;      transmits bottom nybble of W in hex
-; W            ????VVVV        undefined
-       and_lw  0x0f
-       sub_lw  10
-       sub_lw  0
-       bra_n   serial_write_hex_digit_ifnot_ge10
-       add_lw  'a'-('0'+10)
-serial_write_hex_digit_ifnot_ge10
-       add_lw  '0'+10
-       bra     serial_write_char
-
-       end
+ include syncwrite.inc
+ end
 
--- /dev/null
+;======================================================================
+;
+; these routines all use serial_write_char which writes
+; bytes to the serial port synchronously
+
+       include         /usr/share/gputils/header/p18f458.inc
+       radix           dec
+       include         ../iwjpictest/insn-aliases.inc
+
+ udata_acs
+serial_hex_temp res 1
+
+ code
+
+;----------------------------------------
+serial_write_char
+; W            character       undefined
+serial_write_char_loop
+       bt_f_if0        PIR1, TXIF
+       bra             serial_write_char_loop
+       mov_wf          TXREG
+       return
+
+;----------------------------------------
+serial_write_hex
+;      transmits W in hex through serial port, using serial_write_char
+;                      Before          After
+; W                    value           undefined
+; serial_hex_temp      undefined       undefined
+       mov_wf          serial_hex_temp
+       rcall           serial_write_hex_1digit_for_both
+       rcall           serial_write_hex_1digit_for_both
+       return
+
+;--------------------
+serial_write_hex_1digit_for_both
+;      transmits top nybble of serial_hex_temp in hex
+;      through serial port, as above, and swaps nybbles
+;              Before          After
+; W                    any             undefined
+; serial_hex_temp      BBBBaaaa        aaaaBBBB        (BBBB was sent)
+       swap_f  serial_hex_temp
+       mov_fw  serial_hex_temp
+;...
+;--------------------
+serial_write_hex_digit
+;      transmits bottom nybble of W in hex
+; W            ????VVVV        undefined
+       and_lw  0x0f
+       sub_lw  10
+       sub_lw  0
+       bra_n   serial_write_hex_digit_ifnot_ge10
+       add_lw  'a'-('0'+10)
+serial_write_hex_digit_ifnot_ge10
+       add_lw  '0'+10
+       bra     serial_write_char
+
+ include ../iwjpictest/syncwrite.inc
+ end
 
--- /dev/null
+ extern serial_write_char
+ extern serial_write_hex
+ extern serial_write_hex_digit
 
 
 LINK=          gplink -m -o $@ $^
 ASSEMBLE=      gpasm -p 18f458 $(ASFLAGS)
+MERGEHEX=      $(CEBPIC)merge-hex $^ $o
+DOASSEMBLE=    $(ASSEMBLE) -c $< && mv $*.lst $*-asm.lst
 
 %.o:           %.asm $(INCLUDES)
-               $(ASSEMBLE) -c $<
-               mv $*.lst $*-asm.lst
+               $(DOASSEMBLE)
 
 .PRECIOUS:     %.o