рд░реВрдмреА рдмрд╛рдВрдзрдирд╛ рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП

рджреВрд╕рд░реЗ рджрд┐рди, рдпрд╣ libftdi рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдерд╛, рдЬреЛ рдЖрдзреБрдирд┐рдХ рдХрдВрдкреНрдпреВрдЯрд░реЛрдВ рдХреЛ рдЕрдкреНрд░рдЪрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП USB рдХрдВрдкреНрдпреВрдЯрд░реЛрдВ рдХреЛ RS-232 рдпрд╛ TTL рд╕реНрддрд░реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реАрд░рд┐рдпрд▓ рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд╝рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪрд┐рдкреНрд╕ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдПрдлрдПрдлрдЖрдИ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЛ рдЪреБрдирд╛, рдЬреЛ рдЖрдкрдХреЛ рдЧрддрд┐рд╢реАрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдФрд░ рдЙрдирдХреЗ рд▓рд┐рдП рдмрд╛рдЗрдВрдбрд░реНрд╕ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдПрдлрдПрдлрдЖрдИ рдХреЗ рдХрдИ рдлрд╛рдпрджреЗ рд╣реИрдВ рдЬреЛ рдЗрд╕рдХреЗ рдкрдХреНрд╖ рдореЗрдВ рдЦреЗрд▓реЗ рд╣реИрдВ:

рд░реВрдмреА рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдпрдХрд╛рд░реА рднрдВрдбрд╛рд░ ред

рд╢реБрд░реБрдЖрдд


рд╣рдо рдПрдХ рдмрд╛рдзреНрдпрдХрд╛рд░реА рдореЙрдбреНрдпреВрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ libftdi рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ:
require 'ffi' # Represents libftdi ruby bindings. # End-user API represented by {Ftdi::Context} class. module Ftdi extend FFI::Library ffi_lib "libftdi" end 

рдорд╛рдирд╡ рд░рд╣рд┐рдд рд╕рдВрд╕рд╛рдзрди рдкреНрд░рдмрдВрдзрди


Libftdi рдХрд╛ рдореБрдЦреНрдп рд╕рд╛рд░ рдЗрд╕рдХрд╛ рд╕рдВрджрд░реНрдн рд╣реИ, рдЬрд┐рд╕реЗ рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдкрд░ рдкреНрд░рдХрд╛рд╢ рдбрд╛рд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЙрд╕реА рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЗрд╕реЗ рдЬрд╛рд░реА рдХрд░реЗрдВред FFI::ManagedStruct рд╡рд░реНрдЧ рдЕрдкреНрд░рдмрдВрдзрд┐рдд рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рд╕реНрд╡рдд: рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ:

  attach_function :ftdi_new, [ ], :pointer attach_function :ftdi_free, [ :pointer ], :void # Represents libftdi context and end-user API. # @example Open USB device # ctx = Ftdi::Context.new # begin # ctx.usb_open(0x0403, 0x6001) # begin # ctx.baudrate = 250000 # ensure # ctx.usb_close # end # rescue Ftdi::Error => e # $stderr.puts e.to_s # end class Context < FFI::ManagedStruct # layout skipped... # Initializes new libftdi context. # @raise [CannotInitializeContextError] libftdi cannot be initialized. def initialize ptr = Ftdi.ftdi_new raise CannotInitializeContextError.new if ptr.nil? super(ptr) end # Deinitialize and free an ftdi context. # @return [NilClass] nil def self.release(p) Ftdi.ftdi_free(p) nil end end 

FFI :: ManagedStruct рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд▓реЗрдЖрдЙрдЯ (рдореВрд▓ рджреГрд╢реНрдп рд╕реЗ FFI рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рд╕рдВрд░рдЪрдирд╛ рд░реВрдкрд╛рдВрддрд░рдг рдХрд╛ рдирдХреНрд╢рд╛) рджреНрд╡рд╛рд░рд╛ рдорд╛рд░реНрд╢ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реВрдЪрдХ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ, рд╣рдореЗрдВ ftdi_new (рдореВрд▓ рд░реВрдк рд╕реЗ рдореЙрд▓реЛрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) рдХреЙрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдорд┐рд▓рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╕реБрдкрд░рдХреНрд▓рд╛рд╕ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред

рдХрдЪрд░рд╛ рдЗрдХрдЯреНрдард╛ рдХрд░рддреЗ рд╕рдордп, рд░рд┐рд▓реАрдЬрд╝ рдХреНрд▓рд╛рд╕ рд╡рд┐рдзрд┐ рдХреЛ рдореВрд▓ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░-рдкреЙрдЗрдВрдЯрд░ рдХреЗ рд╕рд╛рде рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдЗрд╕реЗ рдореБрдХреНрдд рдХрд░реЗрдВрдЧреЗред

рд╣рдо рдПрдкреАрдЖрдИ рдмрдирд╛рддреЗ рд╣реИрдВ


рдЪреВрдВрдХрд┐ рд╕рднреА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЙрд▓реНрд╕ рд╕рдВрджрд░реНрдн рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рд╣рдо рд╕рднреА рдПрдкреАрдЖрдИ рд╕рдВрджрд░реНрдн рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдмрдирд╛рдПрдВрдЧреЗ рдФрд░ рдПрдХ ctx рд╡рд┐рдзрд┐ рдмрдирд╛рдПрдВрдЧреЗ рдЬреЛ рдЗрди рдХреЙрд▓реНрд╕ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП libftdi рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП рдПрдХ рдкреЙрдЗрдВрдЯрд░ рд▓реМрдЯрд╛рддрд╛ рд╣реИред

рдЕрдзрд┐рдХрд╛рдВрд╢ libftdi рдлрд╝рдВрдХреНрд╢рди рдПрдХ рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рдкреВрд░реНрдгрд╛рдВрдХ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдкрд░рд┐рдгрд╛рдо рд╢реВрдиреНрдп рд╕реЗ рдХрдо рд╣реЛрдиреЗ рдкрд░ рддреНрд░реБрдЯрд┐ рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдФрд░ рдЕрдкрд╡рд╛рдж рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╣рд╛рдпрдХ рд▓рд┐рдЦрдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ:
  private def ctx self.to_ptr end def check_result(status_code) if status_code < 0 raise StatusCodeError.new(status_code, error_string) end nil end 

рдпрд╣рд╛рдБ error_string , рд╡рд╣ рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ libftdi рд╕рдВрджрд░реНрдн рд╕реЗ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреА рд╣реИред

рдЕрдм, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо ftdi_set_interface рдлрд╝рдВрдХреНрд╢рди ftdi_set_interface рд▓рд┐рдП рдкреЛрд░реНрдЯ рд╡рд┐рдХрд▓реНрдк рдФрд░ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреА ftdi_set_interface рдХрд░рддреЗ ftdi_set_interface ред рдЬрд┐рд╕рд╕реЗ рд╣рдо рдирд╛рдЪрддреЗ рд╣реИрдВ:
 enum ftdi_interface { INTERFACE_ANY = 0, INTERFACE_A = 1, INTERFACE_B = 2, INTERFACE_C = 3, INTERFACE_D = 4 }; int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface); 

рдФрд░ рд╣рдореЗрдВ рдХреНрдпрд╛ рдорд┐рд▓рддрд╛ рд╣реИ:
  # Port interface for chips with multiple interfaces. # @see Ftdi::Context#interface= Interface = enum(:interface_any, :interface_a, :interface_b, :interface_c, :interface_d) attach_function :ftdi_set_interface, [ :pointer, Interface ], :int class Context # ... # Open selected channels on a chip, otherwise use first channel. # @param [Interface] new_interface Interface to use for FT2232C/2232H/4232H chips. # @raise [StatusCodeError] libftdi reports error. # @return [Interface] New interface. def interface=(new_interface) check_result(Ftdi.ftdi_set_interface(ctx, new_interface)) new_interface end ... end 


рдмрд╛рдЗрдЯ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ


ASCIIZ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рддреБрдЪреНрдЫ (рдкреНрд░рдХрд╛рд░ :string ) рд╣реИ, рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдПрдХ рд╕рд░рдгреА рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рд╡рд┐рдлрд▓рддрд╛ рдХреЗ рд▓рд┐рдП рдмрд░реНрдмрд╛рдж рд╣реЛрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдПрдлрдПрдлрдЖрдИ рдорд╛рд░реНрд╢рд▓рд░ рдкрд╣рд▓реЗ рд╢реВрдиреНрдп рдмрд╛рдЗрдЯ рдкрд░ рдареЛрдХрд░ рдЦрд╛рддреЗ рд╣реИрдВред

рдмрд╛рдЗрдЯреНрд╕ рдХреА рдПрдХ рд╕рд░рдгреА рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдЯрд╛рдЗрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ :pointer , рдЬрд┐рд╕реЗ рд╣рдо рдПрдлрдПрдлрдЖрдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрдирд╛рдПрдВрдЧреЗ: рдореЗрдореЛрд░реАрдкреЙрдЗрдВрдЯрд░ (рдореЗрдореЛрд░реА рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдмрдлрд░ рдХреЛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдирд╛ рдФрд░ рднрд░рдирд╛)ред

  attach_function :ftdi_write_data, [ :pointer, :pointer, :int ], :int class Context # ... # Writes data. # @param [String, Array] bytes String or array of integers that will be interpreted as bytes using pack('c*'). # @return [Fixnum] Number of written bytes. # @raise [StatusCodeError] libftdi reports error. def write_data(bytes) bytes = bytes.pack('c*') if bytes.respond_to?(:pack) size = bytes.respond_to?(:bytesize) ? bytes.bytesize : bytes.size mem_buf = FFI::MemoryPointer.new(:char, size) mem_buf.put_bytes(0, bytes) bytes_written = Ftdi.ftdi_write_data(ctx, mem_buf, size) check_result(bytes_written) bytes_written end end 


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдмрд┐рд▓реНрдбрд┐рдВрдЧ рдмрд╛рдЗрдВрдбрд░реНрд╕ рдПрдХ рддреБрдЪреНрдЫ рдХрд╛рд░реНрдп рдмрди рдЧрдпрд╛ рд╣реИред

рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЕрдкрдиреЗ рдирд┐рд░реНрдорд╛рдг рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдореИрдВ SWIG рдХреА рджрд┐рд╢рд╛ рдореЗрдВ рджреЗрдЦрдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВред

Source: https://habr.com/ru/post/In142172/


All Articles