<commit_before>require 'origen_link/server/pin'

##################################################
# OrigenLink::Server::Sequencer Class
#    Instance variables:
#      pinmap: hash with ["pin name"] = pin object
#      patternpinindex: hash with ["pin name"] =
#        integer index into vector data
#      patternpinorder: Array with pin names in
#        the vector order
#
#    This class processes messages targeted for
#    pin sequencer interface (vector pattern
#    execution).
#
#    Supported messages:
#      pin_assign (create pin mapping)
#        ex: "pin_assign:tck,3,extal,23,tdo,5"
#
#      pin_patternorder (define vector pin order)
#        ex: "pin_patternorder:tdo,extal,tck"
#
#      pin_cycle (execute vector data)
#        ex: "pin_cycle:H11"
#
#      pin_clear (clear all setup information)
#        ex: "pin_clear:"
#
#      pin_format (setup a pin with return format)
#        first argument is the timeset
#        ex: "pin_format:1,tck,rl"
#
#      pin_timing (define when pin events happen)
#        timing is stored in a timeset hash
#        first argument is the timeset key
#        ex: "pin_timing:1,tdi,0,tdo,1,tms,0
#
#      version (check version of app server is
#        running)
#        ex: "version:"
#        response ex: "P:0.2.0.pre0"
##################################################
module OrigenLink
  module Server
    def self.gpio_dir=(path)
      @gpio_dir = path
    end

    def self.gpio_dir
      @gpio_dir || '/sys/class/gpio'
    end

    class Sequencer
      attr_accessor :version
      attr_reader :pinmap
      attr_reader :patternorder
      attr_reader :cycletiming
      attr_reader :patternpinindex

      ##################################################
      # initialize method
      #    Create empty pinmap, pattern pin index
      #    and pattern order instance variables
      ##################################################
      def initialize
        @pinmap = Hash.new(-1)
        @patternpinindex = Hash.new(-1)
        @patternorder = []
        @cycletiming = Hash.new(-1)
        @version = ''
      end

      ##################################################
      # processmessage method
      #    arguments: message
      #      message format is <group>_<command>:<args>
      #    returns: message response
      #
      #    This method splits a message into it's
      #    command and arguments and passes this
      #    information to the method that performs
      #    the requested command
      ##################################################
      def processmessage(message)
        command = message.split(':')

        case command[0]
        when 'pin_assign'
          pin_assign(command[1])
        when 'pin_patternorder'
          pin_patternorder(command[1])
        when 'pin_cycle'
          pin_cycle(command[1])
        when 'pin_clear'
          pin_clear
        when 'pin_format'
          pin_format(command[1])
        when 'pin_timing'
          pin_timing(command[1])
        when 'pin_timingv2'
          pin_timingv2(command[1])
        when 'version'
          "P:#{@version}"
        else
          'Error Invalid command: ' + command[0].to_s
        end
      end

      ##################################################
      # pin_assign method
      #    arguments: <args> from the message request
      #      see "processmessage" method
      #    returns: "P:" or error message
      #
      #    This method creates a pin instance for each
      #    pin in the pin map and builds the pinmap
      #    hash.  Before the pinmap is created, any
      #    information from a previous pattern run is
      #    cleared.
      ##################################################
      def pin_assign(args)
        pin_clear
        success = true
        fail_message = ''
        argarr = args.split(',')
        0.step(argarr.length - 2, 2) do |index|
          @pinmap[argarr[index]] = Pin.new(argarr[index + 1])
          unless @pinmap[argarr[index]].gpio_valid
            success = false
            fail_message = fail_message + 'pin ' + argarr[index] + ' gpio' + argarr[index + 1] + ' is invalid'
          end
        end
        if success
          'P:'
        else
          'F:' + fail_message
        end
      end

      ########################################################
      # pin_timingv2 method
      #   arguments: <args> from the message request
      #     Should be '1,drive,5,pin,10,pin2,|compare,0,pin3'
      #     First integer is timeset number
      #
      #   returns "P:" or error message
      #
      #   This method sets up a time set.  Any arbitrary
      #   waveform can be generated
      #
      ########################################################
      def pin_timingv2(args)
        # get the tset number
        argarr = args.split(',')
        tset_key = argarr.delete_at(0).to_i
        new_timeset(tset_key)
        args = argarr.join(',')
        
        invalid_pins = []

        # process and load the timeset
        waves = args.split('|')
        waves.each do |w|
          argarr = w.split(',')
          wave_type = argarr.delete_at(0)
          event_data_key = wave_type + '_event_data'
          event_pins_key = wave_type + '_event_pins'
          w = argarr.join(',')
          events = w.split(';')
          events.each do |e|
            argarr = e.split(',')
            event_key = argarr.delete_at(0).to_f
            @cycletiming[tset_key]['events'] << event_key
            @cycletiming[tset_key][event_data_key][event_key] = argarr.delete_at(0)
            # now load the pins for this event
            @cycletiming[tset_key][event_pins_key][event_key] = []
            argarr.each do |pin|
              if @pinmap.key?(pin)
                @cycletiming[tset_key][event_pins_key][event_key] << @pinmap[pin]
              else
                invalid_pins << pin
              end
            end # of argarr.each
          end # of events.each
        end # of waves.each
        @cycletiming[tset_key]['events'].uniq!
        @cycletiming[tset_key]['events'].sort!
        
        # return result
        if invalid_pins.size > 0
          'F:Invalid pins (not in pinmap): ' + invalid_pins.join(', ') 
        else
          'P:'
        end
      end # of def pin_timingv2

      ##################################################
      # new_timeset(tset)
      #   creates a new empty timeset hash
      #
      #   timing format:
      #     ['events'] = [0, 5, 10, 35]
      #     ['drive_event_data'] = {
      #           0: 'data'
      #          10: 'data'
      #          35: '0'
      #         }
      #     ['drive_event_pins'] = {
      #           0: [pin_obj1, pin_obj2]
      #           etc.
      #         }
      ##################################################
      def new_timeset(tset)
        @cycletiming[tset] = {}<commit_msg>lint fix<commit_after>require 'origen_link/server/pin'

##################################################
# OrigenLink::Server::Sequencer Class
#    Instance variables:
#      pinmap: hash with ["pin name"] = pin object
#      patternpinindex: hash with ["pin name"] =
#        integer index into vector data
#      patternpinorder: Array with pin names in
#        the vector order
#
#    This class processes messages targeted for
#    pin sequencer interface (vector pattern
#    execution).
#
#    Supported messages:
#      pin_assign (create pin mapping)
#        ex: "pin_assign:tck,3,extal,23,tdo,5"
#
#      pin_patternorder (define vector pin order)
#        ex: "pin_patternorder:tdo,extal,tck"
#
#      pin_cycle (execute vector data)
#        ex: "pin_cycle:H11"
#
#      pin_clear (clear all setup information)
#        ex: "pin_clear:"
#
#      pin_format (setup a pin with return format)
#        first argument is the timeset
#        ex: "pin_format:1,tck,rl"
#
#      pin_timing (define when pin events happen)
#        timing is stored in a timeset hash
#        first argument is the timeset key
#        ex: "pin_timing:1,tdi,0,tdo,1,tms,0
#
#      version (check version of app server is
#        running)
#        ex: "version:"
#        response ex: "P:0.2.0.pre0"
##################################################
module OrigenLink
  module Server
    def self.gpio_dir=(path)
      @gpio_dir = path
    end

    def self.gpio_dir
      @gpio_dir || '/sys/class/gpio'
    end

    class Sequencer
      attr_accessor :version
      attr_reader :pinmap
      attr_reader :patternorder
      attr_reader :cycletiming
      attr_reader :patternpinindex

      ##################################################
      # initialize method
      #    Create empty pinmap, pattern pin index
      #    and pattern order instance variables
      ##################################################
      def initialize
        @pinmap = Hash.new(-1)
        @patternpinindex = Hash.new(-1)
        @patternorder = []
        @cycletiming = Hash.new(-1)
        @version = ''
      end

      ##################################################
      # processmessage method
      #    arguments: message
      #      message format is <group>_<command>:<args>
      #    returns: message response
      #
      #    This method splits a message into it's
      #    command and arguments and passes this
      #    information to the method that performs
      #    the requested command
      ##################################################
      def processmessage(message)
        command = message.split(':')

        case command[0]
        when 'pin_assign'
          pin_assign(command[1])
        when 'pin_patternorder'
          pin_patternorder(command[1])
        when 'pin_cycle'
          pin_cycle(command[1])
        when 'pin_clear'
          pin_clear
        when 'pin_format'
          pin_format(command[1])
        when 'pin_timing'
          pin_timing(command[1])
        when 'pin_timingv2'
          pin_timingv2(command[1])
        when 'version'
          "P:#{@version}"
        else
          'Error Invalid command: ' + command[0].to_s
        end
      end

      ##################################################
      # pin_assign method
      #    arguments: <args> from the message request
      #      see "processmessage" method
      #    returns: "P:" or error message
      #
      #    This method creates a pin instance for each
      #    pin in the pin map and builds the pinmap
      #    hash.  Before the pinmap is created, any
      #    information from a previous pattern run is
      #    cleared.
      ##################################################
      def pin_assign(args)
        pin_clear
        success = true
        fail_message = ''
        argarr = args.split(',')
        0.step(argarr.length - 2, 2) do |index|
          @pinmap[argarr[index]] = Pin.new(argarr[index + 1])
          unless @pinmap[argarr[index]].gpio_valid
            success = false
            fail_message = fail_message + 'pin ' + argarr[index] + ' gpio' + argarr[index + 1] + ' is invalid'
          end
        end
        if success
          'P:'
        else
          'F:' + fail_message
        end
      end

      ########################################################
      # pin_timingv2 method
      #   arguments: <args> from the message request
      #     Should be '1,drive,5,pin,10,pin2,|compare,0,pin3'
      #     First integer is timeset number
      #
      #   returns "P:" or error message
      #
      #   This method sets up a time set.  Any arbitrary
      #   waveform can be generated
      #
      ########################################################
      def pin_timingv2(args)
        # get the tset number
        argarr = args.split(',')
        tset_key = argarr.delete_at(0).to_i
        new_timeset(tset_key)
        args = argarr.join(',')

        invalid_pins = []

        # process and load the timeset
        waves = args.split('|')
        waves.each do |w|
          argarr = w.split(',')
          wave_type = argarr.delete_at(0)
          event_data_key = wave_type + '_event_data'
          event_pins_key = wave_type + '_event_pins'
          w = argarr.join(',')
          events = w.split(';')
          events.each do |e|
            argarr = e.split(',')
            event_key = argarr.delete_at(0).to_f
            @cycletiming[tset_key]['events'] << event_key
            @cycletiming[tset_key][event_data_key][event_key] = argarr.delete_at(0)
            # now load the pins for this event
            @cycletiming[tset_key][event_pins_key][event_key] = []
            argarr.each do |pin|
              if @pinmap.key?(pin)
                @cycletiming[tset_key][event_pins_key][event_key] << @pinmap[pin]
              else
                invalid_pins << pin
              end
            end # of argarr.each
          end # of events.each
        end # of waves.each
        @cycletiming[tset_key]['events'].uniq!
        @cycletiming[tset_key]['events'].sort!

        # return result
        if invalid_pins.size > 0
          'F:Invalid pins (not in pinmap): ' + invalid_pins.join(', ')
        else
          'P:'
        end
      end # of def pin_timingv2

      ##################################################
      # new_timeset(tset)
      #   creates a new empty timeset hash
      #
      #   timing format:
      #     ['events'] = [0, 5, 10, 35]
      #     ['drive_event_data'] = {
      #           0: 'data'
      #          10: 'data'
      #          35: '0'
      #         }
      #     ['drive_event_pins'] = {
      #           0: [pin_obj1, pin_obj2]
      #           etc.
      #         }
      ##################################################
      def new_timeset(tset)
        @cycletiming[tset] = {}
{'fraction_non_alphanumeric': 0.1796772786742259, 'fraction_numerical': 0.009158307893589184, 'mean_word_length': 2.0166630124972595, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4133852', 'n_tokens_mistral': 4083, 'n_tokens_neox': 3965, 'n_words': 975}