-- Define the protocol
TC_TM_PROTOCOL = Proto("tc_tm", "TC_TM")

local f_sof1 = ProtoField.uint8("TC_TM_PROTOCOL.sof1", "SOF1", base.HEX)
local f_sof2 = ProtoField.uint8("TC_TM_PROTOCOL.sof2", "SOF2", base.HEX)
local f_tm_ctrl = ProtoField.uint8("TC_TM_PROTOCOL.tm_ctrl", "TM Ctrl", base.HEX)
local f_GS_Id = ProtoField.uint8("TC_TM_PROTOCOL.GS_Id", "GS Id", base.HEX)
local f_timestamp = ProtoField.string("TC_TM_PROTOCOL.timestamp", "Timestamp", base.NONE)
local f_ist = ProtoField.string("TC_TM_PROTOCOL.timestamp_ist", "IST TIME ", base.NONE)
local f_pst = ProtoField.string("TC_TM_PROTOCOL.timestamp_pst", "PST TIME", base.NONE)
local f_est = ProtoField.string("TC_TM_PROTOCOL.timestamp_est", "EST TIME", base.NONE)
local f_mt = ProtoField.string("TC_TM_PROTOCOL.timestamp", "MST TIME", base.NONE)
local f_sequence_no = ProtoField.uint16("TC_TM_PROTOCOL.sequence_no", "Sequence No", base.DEC)
local f_sat_id = ProtoField.uint16("TC_TM_PROTOCOL.sat_id", "SAT Id", base.DEC)
local f_qos = ProtoField.uint8("TC_TM_PROTOCOL.qos", "QoS", base.DEC)
local f_sa_id = ProtoField.uint16("TC_TM_PROTOCOL.sa_id", "SA Id", base.DEC)
local f_da_id = ProtoField.uint16("TC_TM_PROTOCOL.da_id", "DA Id", base.DEC)
local f_rm_id = ProtoField.uint8("TC_TM_PROTOCOL.rm_id", "RM Id", base.DEC)
local f_tm_id = ProtoField.uint16("TC_TM_PROTOCOL.tm_id", "TM Id", base.DEC)
local f_co_id = ProtoField.uint16("TC_TM_PROTOCOL.co_id", "Co Id", base.DEC)
local f_tm_len = ProtoField.uint16("TC_TM_PROTOCOL.tm_len", "TM Len", base.DEC)
local f_tm_data = ProtoField.uint8("TC_TM_PROTOCOL.tm_data", "TM Data", base.DEC)
local f_ext_header_len = ProtoField.uint8("TC_TM_PROTOCOL.ext_header_len", "Ext Header Len", base.DEC)
local f_ext_header_data = ProtoField.uint8("TC_TM_PROTOCOL.ext_header_data", "Ext Header Data", base.DEC)
local f_crc = ProtoField.uint8("TC_TM_PROTOCOL.crc", "CRC", base.DEC)
local f_c_mac = ProtoField.uint8("TC_TM_PROTOCOL.c_mac", "C MAC", base.DEC)
local f_eof1 = ProtoField.uint8("TC_TM_PROTOCOL.eof1", "EOF", base.HEX)
local f_tc_id = ProtoField.uint16("TC_TM_PROTOCOL.tc_id", "TC Id", base.DEC)
local f_tc_len = ProtoField.uint16("TC_TM_PROTOCOL.tc_len", "TC Len", base.DEC)
local f_tc_data = ProtoField.uint32("TC_TM_PROTOCOL.tc_data", "TC Data", base.DEC)

-- Add the fields to the protocol
TC_TM_PROTOCOL.fields = {
    f_sof1, f_sof2, f_tm_ctrl,f_GS_Id, f_timestamp, f_sequence_no, f_sat_id, f_ist, f_pst, f_est, f_mt,
    f_qos, f_sa_id, f_da_id, f_rm_id, f_tm_id, f_co_id, f_tm_len, f_tm_data,
    f_ext_header_len, f_ext_header_data, f_crc, f_c_mac, f_eof1,f_tc_id ,f_tc_len ,f_tc_data 
}

------------------------------------------------------------------------------------------------------------------------------------


function TC_dissector(buffer, pinfo, tree)
--Set the protocol coloumn name in wireshark
   local subtree = tree:add(TC_TM_PROTOCOL, buffer(), "TELECOMMAND")
    
    -- Dissect SOF1 and SOF2
    local offset = 0
    
    for i = 0,1000 do
      local data = buffer(i,1):le_uint()
      if data == 0xa5 then
        offset = i
        break
      end
    end
      
    subtree:add(f_sof1 , buffer(offset, 1))
    offset = offset + 1
    
    subtree:add(f_sof2, buffer(offset, 1))
    offset = offset + 1
    
    -- Dissect TC Control byte (TC_Ctrl)
    local tc_ctrl = buffer(offset, 1):le_uint()  -- Get the value of TC Ctrl byte
    subtree:add(f_tm_ctrl , tc_ctrl)
    offset = offset + 1
    
    -- Dissect Timestamp (4 bytes)
    if buffer:len() >= offset + 4 then
        local timestamp = buffer(offset, 4):le_uint()
        local utc_time = os.date("!%Y-%m-%d %H:%M:%S", timestamp)
        subtree:add(f_timestamp, timestamp.." ".."("..utc_time..")" )
        
        local time = timestamp + 19800
        local ist_time = os.date("!%Y-%m-%d %H:%M:%S", time)
        subtree:add(f_ist, ist_time)
        
        time = timestamp - 28800
        local pst_time = os.date("!%Y-%m-%d %H:%M:%S", time) 
        subtree:add(f_pst, pst_time)
        
        time = timestamp - 18000
        local est_time = os.date("!%Y-%m-%d %H:%M:%S", time) 
        subtree:add(f_est, est_time)
        
        time = timestamp - 25200
        local mt_time = os.date("!%Y-%m-%d %H:%M:%S", time) 
        subtree:add(f_mt, mt_time)
        
        offset = offset + 4
    else
        subtree:add(f_timestamp, "Invalid data (timestamp)")
    end
    
    -- Dissect Sequence No (2 bytes)
    if buffer:len() >= offset + 2 then
        local sequence = buffer(offset, 2):le_uint()
        subtree:add(f_sequence_no, sequence)
        offset = offset + 2
    else
       subtree:add(f_sequence_no, "Invalid data (sequence number)")
    end
    
    -- Dissect SAT_Id (1 byte)
    if buffer:len() >= offset + 1 then
        local sat_id = buffer(offset, 1):uint()  -- Get SAT Id (1st byte)
            --offset = offset + 1
            
            if bit.band(sat_id, 0x80) == 0x80 then     --if 7th bit is set and 
                if buffer:len() >= offset + 1 then
                    local second = buffer(offset, 2):le_uint()
                    
                    if bit.band(second, 0x8000) == 0x0000 then    --and 15th bit is set then unset 15th bit 
                    sat_id = buffer(offset, 2):le_uint()
                    sat_id = bit.band(sat_id, 0xFF7F)
                    offset = offset + 1
                    
                    else
                    sat_id = buffer(offset, 2):le_uint()
                    sat_id = bit.band(sat_id, 0x7FFF)  -- and 15th bit is unset then unset the 7th bit
                    offset = offset + 1
                    end
                end
            end
            subtree:add(f_sat_id, sat_id)
            offset = offset + 1
    end
    
    -- Dissect GS_Id (1 byte)
    if buffer:len() >= offset + 1 then
        local gs_id = buffer(offset, 1):uint()  -- Get SAT Id (1st byte)
            --offset = offset + 1
            
            if bit.band(gs_id, 0x80) == 0x80 then
                if buffer:len() >= offset + 1 then
                    local second = buffer(offset, 2):le_uint()
                    
                    if bit.band(second, 0x8000) == 0x0000 then
                    gs_id = buffer(offset, 2):le_uint()
                    gs_id = bit.band(gs_id, 0xFF7F)
                    offset = offset + 1
                    
                    else
                    gs_id = buffer(offset, 2):le_uint()
                    gs_id = bit.band(gs_id, 0x7FFF)
                    offset = offset + 1
                    end
                end
            end
            subtree:add(f_GS_Id, gs_id)
            offset = offset + 1
    end
    
    -- Dissect QoS (1 byte)
    if buffer:len() >= offset + 1 then
        subtree:add(f_qos, buffer(offset, 1))
        offset = offset + 1
    end
    
    -- Dissect SA_Id (Source Application ID) and DA_Id (Destination Application ID)
    if buffer:len() >= offset + 1 then
        local sa_id = buffer(offset, 1):uint()  -- Get source Application Id (1st byte)
            --offset = offset + 1
            
            if bit.band(sa_id, 0x80) == 0x80 then
                if buffer:len() >= offset + 1 then
                   local second = buffer(offset, 2):le_uint()
                    
                    if bit.band(second, 0x8000) == 0x0000 then
                    sa_id = buffer(offset, 2):le_uint()
                    sa_id = bit.band(sa_id, 0xFF7F)
                    offset = offset + 1
                    
                    else
                    sa_id = buffer(offset, 2):le_uint()
                    sa_id = bit.band(sa_id, 0x7FFF)
                    offset = offset + 1
                    end
                end
            end
            subtree:add(f_sa_id, sa_id)
            offset = offset + 1
     end
        
        if buffer:len() >= offset + 1 then
            --subtree:add(f_DA_Id, buffer(offset, 1))
            local da_id = buffer(offset, 1):le_uint()  -- Get Destination Application Id (1st byte)
            --offset = offset + 1
            
            if bit.band(da_id, 0x80) == 0x80 then
                if buffer:len() >= offset + 1 then
                        
 		local second = buffer(offset, 2):le_uint()
                    
                    if bit.band(second, 0x8000) == 0x0000 then
                    da_id = buffer(offset, 2):le_uint()
                    da_id = bit.band(da_id, 0xFF7F)
                    offset = offset + 1
                    
                    else
                    da_id = buffer(offset, 2):le_uint()
                    da_id = bit.band(da_id, 0x7FFF)
                    offset = offset + 1
                    end
                end
            end
            subtree:add(f_da_id, da_id)
            offset = offset + 1
        end
    
    -- Dissect RM_Id (1 byte)
    if buffer:len() >= offset + 1 then
        subtree:add(f_rm_id, buffer(offset, 1))
        offset = offset + 1
    end
    
    -- Dissect TC_Id (2 bytes)
   -- Dissect TC_Id (2 bytes)
	local info_display
 
   local tc_id = buffer(offset, 1):le_uint() -- Read 1 byte for tc_id
   
   if tc_id == 100 or tc_id == 102 or tc_id == 103 then
   pinfo.cols.protocol = "FTM(UL)"
   elseif tc_id == 105 then
   pinfo.cols.protocol = "FTM(DL)"
   else
   pinfo.cols.protocol = "TELECOMMAND"
   end
   
   if buffer:len() >= offset + 2 then  -- Ensure enough data is available to read 2 bytes

    -- Check if the 7th bit (0x80) is set in tc_id
    if bit.band(tc_id, 0x80) == 0x80 then
        if buffer:len() >= offset + 2 then  -- Ensure enough data for the next 2 bytes
           
                    
 		local second = buffer(offset, 2):le_uint()
                    
                    if bit.band(second, 0x8000) == 0x0000 then
                    tc_id = buffer(offset, 2):le_uint()
                    tc_id = bit.band(tc_id, 0xFF7F)
                    offset = offset + 1
                    
                    else
                    tc_id = buffer(offset, 2):le_uint()
                    tc_id = bit.band(tc_id, 0x7FFF)
                    offset = offset + 1
                    end
        end
    end

    -- Add tc_id to the subtree (display in dissection tree)
    subtree:add(f_tc_id, tc_id)
    
    -- Move the offset forward by 1 (since we initially read 1 byte)
    offset = offset + 1
end


    -- Dissect TC_Len (2 bytes)
    local tc_len = 0  -- Declare tc_len as a local variable here
    if buffer:len() >= offset + 2 then
        tc_len = buffer(offset, 2):le_uint()
        subtree:add(f_tc_len, tc_len)
        offset = offset + 2
    end
    
    -- Dissect TC_Data (variable length)
    --local subtree2 = subtree:add(TC_TM_PROTOCOL, buffer(), TC_DATA())
    local data
    if buffer:len() >= offset + tc_len then
          if  tc_len == 0 then
              subtree:add("TC DATA : NIL")
          else
              if tc_id == 621 then
                 	require("hm_dissector")
                	data = HM_TC_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, offset)
                	offset = offset + tc_len  
		          elseif tc_id == 100 then
                	require("ftci_dissector")
			            ftci_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, offset)
                	offset = offset + tc_len 
		          elseif tc_id == 103 then
                	require("ftfci_dissector")
			            ftfci_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, offset)
                	offset = offset + tc_len 
		          elseif tc_id == 102 then
                 	require("ftds_dissector")
                 	ftds_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, offset)
                 	offset = offset + tc_len
		          elseif tc_id == 105 then
                 	require("ftsr_dissector")
          		    ftsr_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, offset)
                 	offset = offset + tc_len
              elseif tc_id == 202 then
                  require("eps_wr_stored_param")
                  eps_tc_wr_stored_param_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, offset)
                  offset = offset + tc_len
              elseif tc_id == 211 then
                  require("tc_eps_set_cntrl_chnl_state")
                  tc_eps_set_cntrl_chnl_state(buffer, pinfo, tree, TC_TM_PROTOCOL, offset)
                  offset = offset + tc_len
                 else
	              for i=0,tc_len - 1 do
        	      subtree:add(f_tc_data, buffer(offset, 1))
      	        	offset = offset + 1
             		end
                 end
	end
    end
    

    -- Check if we can dissect Ext_Header_Len
    if bit.band(tc_ctrl, 0x80) == 0x80 and buffer:len() >= offset + 1 then
        subtree:add(f_ext_header_len, buffer(offset, 1))
        local ext_header_len = buffer(offset, 1):uint()
        offset = offset + 1

        if buffer:len() >= offset + ext_header_len then
	    for i=1,ext_header_len do
            	subtree:add(f_ext_header_data, buffer(offset, 1))
            	offset = offset + 1
		end
        end
   end
    
    -- Dissect CRC (1 byte)
    if buffer:len() >= offset + 1 then
        subtree:add(f_crc, buffer(offset, 1))
        offset = offset + 1
    end
    
    -- Dissect C-MAC/H-MAC (if TC Ctrl bit 4 is set)
    if bit.band(tc_ctrl, 0x10) == 0x10 and buffer:len() >= offset + 32 then
	for i=1,32 do
        	subtree:add(f_c_mac, buffer(offset, 1))
        	offset = offset + 1
	end
    end
    
    -- Dissect EOF (1 byte)
    if buffer:len() >= offset + 1 then
        subtree:add(f_eof1, buffer(offset, 1))
    end
    local string
    
    if tc_id == 621 then
    
    local switch = {
    [9] = function() return "EPS" end, 
    [22] = function() return "ADCS" end,
    [14] = function() return "SBAND" end,
    [15] = function() return "UHF" end,
    [42] = function() return "SENSOR" end,
    [27] = function() return "OBC" end
    }
    string = (switch[data] or function() return "All Module" end)()
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tc_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TC_ID = "..info_display[3]..", Module = " ..info_display[4] -- for info display in wireshark
   
   elseif tc_id == 100 then
    
    string = "FTCI FRAME"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tc_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TC_ID = "..info_display[3]..", " ..info_display[4] -- for info display in wireshark
   
    elseif tc_id == 105 then
    
    string = "FTSR FRAME"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tc_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TC_ID = "..info_display[3]..", " ..info_display[4] -- for info display in wireshark
    
    
    elseif tc_id == 102 then
    
    string = "FTDS FRAME"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tc_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TC_ID = "..info_display[3]..", " ..info_display[4] -- for info display in wireshark
    
  	 elseif tc_id == 103 then
    
    string = "FTFCI FRAME"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tc_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TC_ID = "..info_display[3]..", " ..info_display[4] -- for info display in wireshark
     	
  
    else            
    
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tc_id} --- for info display in wireshark

    
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TC_ID = "..info_display[3] -- for info display in wireshark
    end
end

-----------------------------------------------------------------------------------------------------------------------------------
function TM_dissector(buffer, pinfo, tree)  -- OBC to GS

	local subtree = tree:add(TC_TM_PROTOCOL, buffer(), "TELEMETRY")

    -- Extract the fields in order as defined in the structure
    
    local add
    
    for i = 0,1000 do
      local data = buffer(i,1):le_uint()
      if data == 0xa5 then
        add = i
        break
      end
    end
        
    subtree:add(f_sof1, buffer(add, 1):le_uint())  -- SOF1 in HEX
    add = add + 1
    
    subtree:add(f_sof2, buffer(add, 1):le_uint())  -- SOF2 in HEX
    add = add + 1
    
    local tm_ctrl = buffer(add, 1):le_uint()
    subtree:add(f_tm_ctrl, buffer(add, 1):le_uint())  -- TM Ctrl in HEX
    add = add + 1
    -- Dissect timestamp
    local timestamp = buffer(add, 4):le_uint()
    local utc_time = os.date("!%Y-%m-%d %H:%M:%S", timestamp)
    subtree:add(f_timestamp, timestamp.." ".."("..utc_time..")" )
    
    local time = timestamp + 19800
        local ist_time = os.date("!%Y-%m-%d %H:%M:%S", time)
        subtree:add(f_ist, ist_time)
        
        time = timestamp - 28800
        local pst_time = os.date("!%Y-%m-%d %H:%M:%S", time) 
        subtree:add(f_pst, pst_time)
        
        time = timestamp - 18000
        local est_time = os.date("!%Y-%m-%d %H:%M:%S", time) 
        subtree:add(f_est, est_time)
        
        time = timestamp - 25200
        local mt_time = os.date("!%Y-%m-%d %H:%M:%S", time) 
        subtree:add(f_mt, mt_time)
        
    add = add + 4
   
    subtree:add(f_sequence_no, buffer(add, 2):le_uint())  -- Sequence No in HEX
    add = add + 2
       
-- My logic for SAT Id
    local magic = buffer(add, 1):le_uint()

    if bit.band(magic, 0x80) == 0 then
        subtree:add(f_sat_id, buffer(add, 1):le_uint())  -- SAT Id in HEX
	add=add+1
    else
	
	magic=buffer(add, 2):le_uint()
	local dummy=magic & 0x8000    --to check 7th byte is 1
	if dummy == 0 then
		magic = magic & 0xff7f -- if 15th bit is 0 set 7th bit 0
	else 
		magic = magic & 0x7fff -- if 15 bit is 1 set 15th bit to 0
	end
        subtree:add(f_sat_id, magic)  -- SAT Id in HEX
	add=add+2
	
    end

    -- QoS in HEX
    subtree:add(f_qos, buffer(add, 1):le_uint())
    add=add+1

    -- My logic for SA Id
    magic = buffer(add, 1):le_uint()
    if bit.band(magic, 0x80) == 0 then
        subtree:add(f_sa_id, buffer(add, 1):le_uint())  -- SA Id in HEX
	add=add+1
    else
	magic=buffer(add, 2):le_uint()
	local dummy=magic & 0x8000
	if dummy == 0 then
		magic = magic & 0xff7f
	else 
		magic = magic & 0x7fff
	end 
        subtree:add(f_sa_id,magic)  -- SA Id in HEX
	add=add+2
    end

    -- My logic for DA Id
    magic = buffer(add, 1):uint()
    if bit.band(magic, 0x80) == 0 then
        subtree:add(f_da_id, buffer(add, 1):le_uint())  -- DA Id in HEX
	add=add+1
    else
	magic=buffer(add, 2):le_uint()
	local dummy=magic & 0x8000
	if dummy == 0 then
		magic = magic & 0xff7f
	else 
		magic = magic & 0x7fff
	end
        subtree:add(f_da_id, magic)  -- DA Id in HEX
	add=add+2
    end

    -- RM Id in HEX
    subtree:add(f_rm_id, buffer(add, 1):le_uint())
    add=add+1

    -- My logic for TM Id
    local info_display    -- for display in wireshark
    local tm_id
    
    magic = buffer(add, 1):uint()
    if bit.band(magic, 0x80) == 0 then
        subtree:add(f_tm_id, buffer(add, 1):le_uint())  -- TM Id in HEX
	 info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,buffer(add, 1):le_uint()} --- for info display in wireshark
	add=add+1
    else
	magic=buffer(add, 2):le_uint()
	local dummy=magic & 0x8000
	if dummy == 0 then
		magic = magic & 0xff7f
	else 
		magic = magic & 0x7fff
	end
        subtree:add(f_tm_id, magic)  -- TM Id in HEX
	      add=add+2
    end

    tm_id = magic
    
   if tm_id == 104 or tm_id == 106 or tm_id == 107 then
   pinfo.cols.protocol = "FTM(DL)"
   elseif tm_id == 101 then
   pinfo.cols.protocol = "FTM(UL)"
   else
   pinfo.cols.protocol = "TELEMETRY"
   end
    
    -- Co Id in HEX
    subtree:add(f_co_id, buffer(add, 2):le_uint())
    add=add+2
    
    -- TM Len in HEX
    local tm_len
    
    magic = buffer(add, 2):le_uint()
    tm_len = magic
    subtree:add(f_tm_len, buffer(add, 2):le_uint())
    add=add+2

    --  logic for TM Data
  local array
	--local subtree2 = subtree:add(TC_TM_PROTOCOL, buffer(), "TM_DATA")
 
   -- Dissect TM_Data (variable length)
	
	

      if tm_id == 621 or  tm_id == 815 or  tm_id == 104 or  tm_id == 107 or  tm_id == 101 or  tm_id == 106  or tm_id == 200 or tm_id == 201 or tm_id == 202 or 
      tm_id == 129 or tm_id == 241 or tm_id == 130 or tm_id == 133 or tm_id == 134 or tm_id == 135 or tm_id == 137 or tm_id == 195 or tm_id == 196 or 
      tm_id == 184 or tm_id == 855 or tm_id == 857 or tm_id == 800 or tm_id == 819 or tm_id == 823 or tm_id == 398 or tm_id == 413 or tm_id == 461 or
      tm_id == 463 or tm_id == 464 or tm_id == 468 or tm_id == 474 or tm_id == 475 or tm_id == 412 or tm_id == 253 or tm_id == 411 or tm_id == 211 or
      tm_id == 212 then
      			if tm_id == 621  then
      				require("hm_dissector")
        			array = HM_TM_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add, tm_len)
        			add = add + tm_len

 			      elseif tm_id == 815  then
 				      require("bcon")
        			bcon_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add, tm_len)
        			add = add + tm_len

			       elseif tm_id == 104 then
       			      require("ftci_dissector")
					        ftci_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
          			  add = add + tm_len 
            elseif tm_id == 107 then
       			      require("ftfci_dissector")
					        ftfci_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
          			  add = add + tm_len
		        elseif tm_id == 101 then 
      				require("ftsr_dissector")
      				ftsr_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
      				add = add + tm_len
				    elseif tm_id == 106 then 
			        require("ftds_dissector")
     			    ftds_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
     				   add = add + tm_len
            elseif tm_id == 200 then
              require("eps_get_live_param");
              eps_get_live_param_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
              add = add + tm_len
            elseif tm_id == 201 then
              require("eps_rd_stored_param");
              eps_rd_stored_param_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
              add = add + tm_len
            elseif tm_id == 202 then
              require("eps_tm_wr_stored_param");
              eps_tm_wr_stored_param_dissector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
              add = add + tm_len
            elseif tm_id == 129 then
              require("tm_get_adcs_state");
              tm_get_adcs_state(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
              add = add + tm_len
            elseif tm_id == 253 then
              require("tm_adcs_state_cfg");
              tm_adcs_state_cfg(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
              add = add + tm_len
            elseif tm_id == 241 then
              require("tm_adcs_get_est_attitude_angl");
              tm_get_adcs_estimated_angle(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
              add = add + tm_len
	          elseif tm_id == 130 then 
	            require("tm_get_adcs_tle");
	            tm_get_adcs_tle(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 133 then 
              require("tm_get_adcs_mag_field_vector");
	            tm_get_adcs_mag_field_vector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 134 then 
              require("tm_get_adcs_css_vector");
	            tm_get_adcs_css_vector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 135 then 
	            require("tm_get_adcs_fss_vector");
	            tm_get_adcs_fss_vector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 137 then 
	            require("tm_get_adcs_sensor_vector");
	            tm_get_adcs_sensor_vector(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 195 then 
	            require("tm_get_adcs_commanded_wheel_speed");
	            tm_get_command_wheel_speed(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 196 then 
	            require("tm_get_adcs_rw_speed_measure");
	            tm_get_adcs_rw_speed_measure(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 184 then 
	            require("tm_get_adcs_est_rate");
	            tm_get_adcs_est_rate(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 855 then 
	            require("tm_get_sdr_tmr_cfg");
	            tm_get_sdr_tmr_cfg(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 857 then 
	            require("tm_get_sdr_rssi_cfg");
	            tm_get_sdr_rssi_cfg(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 800 then 
	            require("tm_comms_uhf_get_tm_info");
	            tm_comms_uhf_get_tm_info(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 819 then 
	            require("tm_comms_uhf_get_tm_store");
	            tm_comms_uhf_get_tm_store(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 823 then 
	            require("tm_comms_uhf_dbg_cb");
	            tm_comms_uhf_dbg_cb(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 398 then 
	            require("tm_get_comms_tm_info");
	            tm_get_comms_tm_info(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 413 then 
	            require("tm_sband_get_tm_store");
	            tm_sband_get_tm_store(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 461 then 
	            require("tm_get_sband_version");
	            tm_get_sband_version(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 463 then 
	            require("tm_sband_get_device_conf");
	            tm_sband_get_device_conf(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 464 then 
	            require("tm_sband_get_feature_select");
	            tm_sband_get_feature_select(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 468 then 
	            require("tm_sband_get_product_key");
	            tm_sband_get_product_key(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 474 then 
	            require("tm_get_sband_dbg_cb");
	            tm_get_sband_dbg_cb(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 475 then 
	            require("tm_get_sband_tx_rx_on_ts");
	            tm_get_sband_tx_rx_on_ts(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 412 then 
	            require("tm_sband_get_tm_all");
	            tm_sband_get_tm_all(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 411 then 
	            require("tm_comms_beacon_tx");
	            tm_comms_beacon_tx(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 211 then 
	            require("tm_eps_set_cntrl_chnl_state");
	            tm_eps_set_cntrl_chnl_state(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len
            elseif tm_id == 212 then 
	            require("tm_get_eps_dev_hw_sts");
	            tm_get_eps_dev_hw_sts(buffer, pinfo, tree, TC_TM_PROTOCOL, add)
	            add = add + tm_len


	end

   
      else
        for i=0,magic-1 do
	        subtree:add(f_tm_data, buffer(add, 1):le_uint())
	        add=add+1
        end
      end
    
      
    -- Ext Header Len in HEX
    if bit.band(tm_ctrl, 0x80) == 0x80   then
    	magic=  buffer(add, 1):uint()
    	subtree:add(f_ext_header_len, buffer(add, 1):uint())
    	add=add+1

    --  logic for Ext Header Data
    	for i=0,magic-1 do
	subtree:add(f_ext_header_data, buffer(add, 1):uint())  -- Ext Header Data in HEX
	add=add+1
	end
    end
    -- CRC in HEX
    subtree:add(f_crc, buffer(add, 1):le_uint())
	add=add+1

    -- C MAC in HEX
	--magic = buffer(, 1):le_uint() -- tm control
    if bit.band(tm_ctrl, 0x10) == 0x10   then
	for i=1,32 do
    		subtree:add(f_c_mac, buffer(add, 1):uint())
		add=add+1    
 	end   
    end
    -- EOF1 in HEX
    subtree:add(f_eof1, buffer(add, 1):uint())
    
    local string
    if tm_id == 621 then
    
    	local switch = {
    	[0] = function() return "EPS" end,
    	[1] = function() return "ADCS" end,
    	[2] = function() return "SBAND" end,
    	[3] = function() return "UHF" end,
    	[4] = function() return "SENSOR" end,
    	[5] = function() return "OBC" end,
    	[6] = function() return "ERROR HANDLER" end
    	}
    	string = (switch[array[1]] or function() return "All Module" end)()
    
    
    
    	info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tm_id, string, array[2], array[3]} --- for info display in wireshark

	 
	pinfo.cols.info ="seq_no = " ..info_display[1]..", TS = " ..info_display[2]..", TM ID = "..info_display[3]..", Module = "..info_display[4]..", Queue id = "..info_display[5]..", Number of instance = "..info_display[6] -- for info display in wireshark
 
 elseif tm_id == 104 then
    
    string = "FTCI FRAME"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tm_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TM_ID = "..info_display[3]..", " ..info_display[4] -- for info display in wireshark
   
    elseif tm_id == 101 then
    
    string = "FTSR FRAME"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tm_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TM_ID = "..info_display[3]..", " ..info_display[4] --for info display in wireshark
    
    
    elseif tm_id == 106 then
    
    string = "FTDS FRAME"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tm_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TM_ID = "..info_display[3]..", " ..info_display[4] -- for info display in wireshark
    
  	 elseif tm_id == 107 then
    
    string = "FTFCI FRAME"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tm_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TM_ID = "..info_display[3]..", " ..info_display[4] -- for info display in wireshark
    
    elseif tm_id == 815 then
   string = "BEACON"
    info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tm_id, string} --- for info display in wireshark
    pinfo.cols.info ="seq_no = " ..info_display[1] ..", TS = " ..info_display[2]..", TM_ID = "..info_display[3]..", " ..info_display[4] -- for info display in wireshark
 
    else
        info_display= {buffer(11, 2):le_uint(),buffer(7, 4):le_uint() ,tm_id} --- for info display in wireshark
    
	 
	pinfo.cols.info ="seq_no = " ..info_display[1]..", TS = " ..info_display[2]..", TM ID = "..info_display[3] -- for info display in wireshark
    end
    -- Check if the buffer contains enough data for the expected total length
   --if buffer:len() < 38 + buffer(21, 2):uint() then
     --   subtree:add_expert_info(PI_MALFORMED, PI_WARN, "Incomplete data")
    --end
end
-- Register the dissector for udp port 


-------------------------------------------------------------------------------------------------------------------------------
-- Dissector function
function TC_TM_PROTOCOL.dissector(buffer, pinfo, tree)
	-- Register protocol in preferences (add this part)
	--my_udp_protocol:register_preference()

    pinfo.cols.protocol = "TC_TM"

  local offset1
    
    for i = 0,1000 do
      local data = buffer(i,1):le_uint()
      if data == 0xa5 then
        offset1 = i
        break
      end
    end
    
    offset1 = offset1 + 2
    -- Create a subtree for this protocol
    --local subtree = tree:add(my_udp_protocol, buffer(), "TE")
    
    

	local direction = buffer(offset1, 1):le_uint()  -- taking tM or tc control byte
 
    if direction & 0x40 == 0x40 then      -- if 6th bit is set then it is TM   
	    TM_dissector(buffer, pinfo, tree)  -- OBC to GS
         
    else
      TC_dissector(buffer, pinfo, tree)   -- GS to OBC
   
    end
end
------------------------------------------------------------------------------------------------------------------------------------------------

-- Add a preference for the port number
TC_TM_PROTOCOL.prefs.port = Pref.uint("UDP Port", 6779, "UDP port for TC_TM protocol")

-- Register the dissector based on the preference
function TC_TM_PROTOCOL.init()
    local udp_table = DissectorTable.get("udp.port")
    udp_table:add(TC_TM_PROTOCOL.prefs.port, TC_TM_PROTOCOL)
end