#! /usr/bin/python -i
# encoding: utf-8

import sys
if "solopath" not in sys.modules: 
    sys.path[1:1] = [".."]

from ppss_table import *
from solomsgclass import HK_T_to_ADC

class step_ppss(ppss_table):
    revision = "$Revision: 5168 $"

    TAG_HK = 0x44
    TAG_PHA = 0x54
    
    HK_cadence = 600
    PHA_cadence = 600
    DRIBBLE_cadence = 3600
    ICU_cadence = 60
    OH_SETPOINT_C = -45
    OH_SETPOINT = HK_T_to_ADC(OH_SETPOINT_C)
    OH_DC = 104
    dps = None
        
    ix1_thr = [62]*32
    ix2_thr = [62]*32
    ix_conf_incr = 30

    def __init__(self, dps=None, small=True, large=True, **kwargs):
        ppss_table.__init__(self)
        self.revision = max(self.revision, ppss_table.revision)
        self.dps = dps
        self.assemble(small=small, large=large, **kwargs)

    def do_init(self):
        self += ppss_item(  1, modulus_always, msg0(ev_enable=0, l3_enable=0, pha_enable=0, ix1enable=0, ix2enable=0), STOP_DATA=True)
        self += ppss_item(2000, modulus_always, msg0(ix1enable=1, ix2enable=1, ev_enable=1, l3_enable=1, pha_enable=1, hist_base='T'), START_DATA=True)

        self += ppss_item(1950, modulus_always, ix_reset(reset=0, gap=0), IX_ARESET=True)
        self += ppss_item(99, ppss_modulus(60,0), opheater(dcmax=self.OH_DC, setpoint=self.OH_SETPOINT), search=True, OPHEATER=True)

    def do_hk(self):
        
        # Counter readout
        self += ppss_item(    420, ppss_modulus(self.HK_cadence,    0), read_counters(tag=self.TAG_HK, a=0x30, n=16, wsize=2), search=True, HK=True)
        self += ppss_item(    445, ppss_modulus(self.HK_cadence,    0), read_counters(tag=self.TAG_HK, a=0x00, n=16, wsize=2), search=True, HK=True)
        self += ppss_item(    470, ppss_modulus(self.ICU_cadence,   0), read_counters(tag=0x25, a=0x30, n=16, wsize=2), search=True, ICU=0x25)
        self += ppss_item(    505, ppss_modulus(self.ICU_cadence,   0), read_counters(tag=0x26, a=0x00, n=16, wsize=2), search=True, ICU=0x26)
        
        # Register readout
        self += ppss_item(      4, ppss_modulus(self.HK_cadence,    1), read_reg(0x3ff, tag=self.TAG_HK), HK=True, search=True)
        self += ppss_item(     50, ppss_modulus(self.ICU_cadence,   1), read_reg(0x3ff, tag=0x21), search=True, ICU=0x21)
        self += ppss_item(    190, ppss_modulus(self.HK_cadence,    1), msg0(reset_errors=True), search=True, RESET_ERRORS=True)

        # ICU HK packet parameters, L3 trigger classes, msgs received
        self += ppss_item(      4, ppss_modulus(self.ICU_cadence,   2), read_counters(tag=0x27, a=0x36, n=4, wsize=1), L3CNTR=True, search=True, ICU=0x27)
        self += ppss_item(     50, ppss_modulus(self.ICU_cadence,   2), read_counters(tag=0x28, a=0x28, n=1, wsize=2), MSGCNTR=True, search=True, ICU=0x28)
        
        # STEP HK parameters, voltages, bias and temperatures
        self += ppss_item(      4, ppss_modulus(self.ICU_cadence,  11), step_get_hk(tag=0x23, temp_spy=1, temp_reg=0xd, compressed=False), search=True, ICU=0x23, STEP_HK=True)
        self += ppss_item(      4, ppss_modulus(self.HK_cadence,   15), step_get_hk(tag=self.TAG_HK, temp_spy=1, temp_reg=0xd), search=True, HK=True, STEP_HK=True)
        self += ppss_item(      4, ppss_modulus(self.ICU_cadence,   0), read_counters(n=128, step_l1=True, wsize=2), ICU=0x2E, search=True, STEP_L1CNTR=True)
        self += ppss_item(    610, ppss_modulus(self.HK_cadence,    0), read_counters(n=128, step_l1=True, clear=True, wsize=2), HK=True, search=True, STEP_L1CNTR=True)
        
        # IDe-Fx HK, registers and tempererature readout
        self += ppss_item(      4, ppss_modulus(self.ICU_cadence,  16), ix_get_hk(tag=0x2F), ICU=0x2F, search=True)
        self += ppss_item(      4, ppss_modulus(self.HK_cadence,   20), ix_get_hk(tag=self.TAG_HK), search=True, HK=True)

        # increment the index registers for table and EEPROM dribble
        self += ppss_item(     4, ppss_modulus(self.DRIBBLE_cadence,   0), set_index_reg(misc_page_incr=128), search=True, EEPROM_INCR=True)
        self += ppss_item(     4, ppss_modulus(self.DRIBBLE_cadence,   0), set_index_reg(dump_page_incr=64), search=True, TABLE_INCR=True)
        self += ppss_item(     4, ppss_modulus(self.DRIBBLE_cadence,   8), read_counters(tag=self.TAG_HK, a=0x40, n=8,  wsize=2, clear=True), search=True, HK=True)
        self += ppss_item(     4, ppss_modulus(self.DRIBBLE_cadence,  68), read_counters(tag=self.TAG_HK, a=0x10, n=28, wsize=2, clear=True), search=True, HK=True)
        self += ppss_item(     4, ppss_modulus(self.DRIBBLE_cadence, 128), read_eeprom(tag=self.TAG_HK, n=128, idx=True), search=True, EEPROM=True, HK=True)
        self += ppss_item(     4, ppss_modulus(self.DRIBBLE_cadence, 188), read_table(tag=self.TAG_HK, n=64, idx=True), search=True, TABLES=True, HK=True)

        # clear 
        self += ppss_item(1900, ppss_modulus(self.HK_cadence, 11), msg0(reset_deadtime=1), search=True)

    def do_pha(self, us=20):
        # toggle PHA page and clear the new pahge
        self += ppss_item(us, ppss_modulus(self.PHA_cadence, 0), msg0(toggle_pha=1, clear_pha=1), search=True, TOGGLE_PHA=True)

        # PHA buffers, these are 1kByte each, rather large
        for i in range(16):
            self += ppss_item(us, ppss_modulus(self.PHA_cadence, 7+10*i), read_sram(tag=self.TAG_PHA, a=256*i, n=256, pha=True), search=True, PHA=True)

    def do_ix_config(self, small=True, large=True, ix1_thr=None, ix2_thr=None, ix1_test=0, ix2_test=0):

        if not ix1_thr:
            ix1_thr = self.ix1_thr
        if not ix2_thr:
            ix2_thr = self.ix2_thr

        if not large:
            ix1_thr = [i if p in ix.SMALL_PIXELS else 63 for i, p in zip(ix1_thr,range(32))]
            ix2_thr = [i if p in ix.SMALL_PIXELS else 63 for i, p in zip(ix2_thr,range(32))]
        elif not small:
            ix1_thr = [i if p in ix.LARGE_PIXELS else 63 for i, p in zip(ix1_thr,range(32))]
            ix2_thr = [i if p in ix.LARGE_PIXELS else 63 for i, p in zip(ix2_thr,range(32))]

        ix_config_time = 1000
        ix_conf_modulus = ppss_modulus(600, 21)
        incr = self.ix_conf_incr

        self += ppss_item(ix_config_time, ix_conf_modulus, ix_rsm(2, ix=3), IX_RSM=True)
        self += ppss_item(ix_config_time + incr, ix_conf_modulus, ix_selfilter(2, ix=3), IX_SELFILTER=True)
        self += ppss_item(ix_config_time + 2*incr, ix_conf_modulus, ix_test_reg(ix1_test, ix=1), IX_TESTREG0=True)
        self += ppss_item(ix_config_time + 3*incr, ix_conf_modulus, ix_test_reg(ix2_test, ix=2), IX_TESTREG1=True)
        self += ppss_item(ix_config_time + 4*incr, ix_conf_modulus, ix_i0(2, ix=3), IX_I0=True)
        self += ppss_item(ix_config_time + 5*incr, ix_conf_modulus, ix_icomp(0, ix=3), IX_ICOMP=True)
        thrs_us0 = ix_config_time + 6 * incr
        self += ppss_items(thrs_us0, ix_conf_modulus, ix_thresholds(ix1_thr, ix=1),incr=incr, IX_THR0=True)
        thrs_us1 = thrs_us0 + 2 * incr + 2 * incr
        self += ppss_items(thrs_us1, ix_conf_modulus, ix_thresholds(ix2_thr, ix=2),incr=incr, IX_THR1=True)

    def do_step_config(self, small=True, large=True):
        conf_us = 950
        step_conf_modulus = modulus_always
        if not large:
            self += ppss_item(conf_us, step_conf_modulus, step_config_l1_l2(max_large=0, max_small=15, max_bg=1, max_sum=16, min_dt=0, read_delay=24), L1L2=True)
        elif not small:
            self += ppss_item(conf_us, step_conf_modulus, step_config_l1_l2(max_large=15, max_small=0, max_bg=1, max_sum=16, min_dt=0, read_delay=24), L1L2=True)
        else:
            self += ppss_item(conf_us, step_conf_modulus, step_config_l1_l2(max_large=15, max_small=15, max_bg=2, max_sum=32, min_dt=0, read_delay=24), L1L2=True)
        self += ppss_item(conf_us+20, step_conf_modulus, step_config_all_acq(all=(0,0), acq=(1,5)), ALLACQ=True)

    def make_HK_table(self):
        hk = self.copy()
        no_HK = []
        no_HK.extend(hk.find_flags("HK"))
        no_HK.extend(hk.find_flags("PHA"))
        no_HK.extend(hk.find_flags("START_DATA"))
        no_HK.extend(hk.find_flags("SCIMEM"))
        no_HK.extend(hk.find_flags("DPS"))
        no_HK.extend(hk.find_flags("DPS_L3"))
        no_HK.extend(hk.find_flags("STEP_L1CNTR"))
        for p in no_HK:
            p.mod = modulus_never
        return hk

    def do_science(self):
        self.science(100000, self.dps, disable_l3=False)
        self.science(799999, [self.dps["clear"]], disable_l3=False)

    def do_fini(self):
        self+= ppss_item(999999, modulus_never, msg0(pps=1))
        self+= ppss_item(1111111, modulus_always, msg0(stop_pps=1))
        self+= ppss_item(0x1000000, modulus_never, noop_msg)

    def assemble(self, small=True, large=True, **kwargs):
        self.do_init()
        self.do_ix_config(small=small, large=large, **kwargs)
        self.do_step_config(small=small, large=large)
        self.do_hk()
        self.do_pha()
        self.do_science()
        self.do_fini()
    
    def set_dps_flags(self, msg=None, dps=None, set=2, clear=0):
        if not dps:
            dps = self.find_flags("DPS")
        dps = [i for i in dps if (i.msg.ad & 0xff00) == 0x0300]
        for d in dps:
            d.msg.da |= set<<36
            d.msg.da &= ~(clear<<36) & 0xffffffffff
            d.msg.sz = 3
            if msg:
                d(msg)
        return dps

    def thres(self, msg, thr, ixx, large=True, small=True):
        try:
            if large is False:
                thr = [p if i in ix.SMALL_PIXELS else 63 for i,p in zip(range(32),thr)]
            if small is False:
                thr = [p if i in ix.LARGE_PIXELS else 63 for i,p in zip(range(32),thr)]
        except:
            pass
        if ixx == 0:
            return
        if ixx == 3:
            pp = self.find_flags("IX_THR1")
            mm = ix_thresholds(thr, ix=2)
            for p,m in zip(pp,mm):
                ppss_item(p.us, p.mod, m, index=p.index)(msg)
            sys.stderr.write("IX1 Thresholds set to: %s\n"%(str(thr)))
            ixx = 1
        pp = self.find_flags("IX_THR%d"%(ixx-1))
        mm = ix_thresholds(thr, ix=ixx)
        for p,m in zip(pp,mm):
            ppss_item(p.us, p.mod, m, index=p.index)(msg)
        sys.stderr.write("IX%d Thresholds set to: %s\n"%(ixx-1, str(thr)))

    def testreg(self, msg, testreg=0, ixx=3):
        if ixx == 0:
            return
        if ixx == 3:
            p = self.find_flags("IX_TESTREG1")[0]
            m = ix_test_reg(testreg, ix=2)
            ppss_item(p.us, p.mod, m, index=p.index)(msg)
            sys.stderr.write("IX1 TESTREG set to 0x%08x"%testreg)
            ixx = 1
        p = self.find_flags("IX_TESTREG%d"%(ixx-1))[0]
        m = ix_test_reg(testreg, ix=ixx )
        ppss_item(p.us, p.mod, m, index=p.index)(msg)
        sys.stderr.write("IX%d TESTREG set to 0x%08x"%(ixx-1,testreg))

    def set_opheater_setpoint(self, msg, T):
        p = self.find_flags("OPHEATER")[0]
        ppss_item(p.us, p.mod, opheater(dcmax=self.OH_DC, setpoint=HK_T_to_ADC(T)), index=p.index)(msg)
        sys.stderr.write("OP heater setpoint: %d C = %d ADC\n" %(T, HK_T_to_ADC(T)))

class ppss_small(step_ppss):
    def __init__(self, dps, **kwargs):
        step_ppss.__init__(self, dps, small=True, large=False, **kwargs)

class ppss_large(step_ppss):
    def __init__(self, dps, **kwargs):
        step_ppss.__init__(self, dps, large=True, small=False, **kwargs)

class ppss_calib(step_ppss):
    def assemble(self, **kwargs):
        step_ppss.assemble(self, **kwargs)
        self.do_streaming()

    def do_science(self, **kwargs):
        pass

    def do_pha(self, **kwargs):
        pass

    def do_streaming(self):
        s = self.find_flags("STOP_DATA")[0]
        self += ppss_item(  s.us, s.mod, msg0(ev_enable=0, l3_enable=0, pha_enable=0, ix1enable=0, ix2enable=0, streaming=0), STOP_DATA=True, replace=True, force=True)
        s = self.find_flags("START_DATA")[0]
        self += ppss_item(s.us, s.mod, msg0(ix1enable=1, ix2enable=1, ev_enable=0, l3_enable=0, pha_enable=0, hist_base='T', streaming=1), START_DATA=True, replace=True, force=True)

class ppss_emc(step_ppss):
    def do_science(self):
        pass

    def do_phs(self):
        pass

    def do_hk(self):
        step_ppss.do_hk(self)
        p = self.find_flags("STEP_L1CNTR")
        for pp in p:
            if "ICU" in pp.flags:
                self += ppss_item(pp.us, ppss_modulus(5, 0), pp.msg, index=pp.index, replace=True, force=True, STEP_L1CNTR=True, ICU=pp.flags["ICU"])


        p = self.find_flags("STEP_HK")
        for pp in p:
            if "ICU" in pp.flags:
                self += ppss_item(pp.us, ppss_modulus(5,  3), pp.msg, index=pp.index, replace=True, force=True, ICU=pp.flags["ICU"], STEP_HK=True)

class ppss_pulser(step_ppss):
    def __init__(self, dps, large=True, small=False, **kwargs):
        step_ppss.__init__(self, dps, large=large, small=small, **kwargs)

    def assemble(self, **kwargs):
        step_ppss.assemble(self, **kwargs)
        self.do_pulser()

    def do_pulser(self):
        # cycle testreg
        r = self.find_flags("IX_THR1")[-1]
        us = r.us + 2 * self.ix_conf_incr
        for i in range(32):
            self += ppss_item(us+i*1, ppss_modulus(60, 1+i), ix_test_reg(1<<i, ix=3), CALIB_TR=True)
        self += ppss_item(us+32, ppss_modulus(60, 33), ix_test_reg(0, ix=3), CALIB_TR=True)

        # cycle pulser
        r = self.find_flags("IX_ARESET")[0]
        us = r.us + 20
        for i in range(0, 2):
            for j in range(0, 4):
                self += ppss_item(us+i*4+j, ppss_modulus(600, 60*(i*4+j)), step_pulser(j*2+4, 500, i), CALIB_PULSER=True)
        self += ppss_item(us+8, ppss_modulus(600, 60*8), step_pulser(0,0,0), CALIB_PULSER=True)

class ppss_pulser_calib(ppss_calib, ppss_pulser):
    def __init__(self, **kwargs):
        ppss_calib.__init__(self, **kwargs)

    def assemble(self, **kwargs):
        ppss_calib.assemble(self, **kwargs)
        self.do_pulser()

    def do_science(self, **kwargs):
        ppss_calib.do_science(self, **kwargs)
    
    def do_pha(self, **kwargs):
        ppss_calib.do_pha(self, **kwargs)

def main():
    import step_dps
    t = step_ppss(dps=step_dps.step_dps())
    sys.stderr.write("PPSS large pixels:\n")
    sys.stderr.write(str(t))
    with file("step_ppss_large.dump", "w") as f:
        f.write(t.dump())
    with file("step_ppss_large.msg", "w") as f:
        f.write(t.dump(func="msg"))
    return t

if __name__ == '__main__':
    main()

