github.com/la5nta/wl2k-go@v0.11.8/rigcontrol/hamlib/libhamlib.go (about)

     1  // Copyright 2015 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
     2  // Use of this source code is governed by the MIT-license that can be
     3  // found in the LICENSE file.
     4  
     5  // +build cgo
     6  // +build libhamlib
     7  
     8  package hamlib
     9  
    10  /*
    11  #cgo LDFLAGS: -lhamlib
    12  #include <string.h>
    13  #include <hamlib/rig.h>
    14  
    15  void setBaudRate(RIG *r, int rate);
    16  int add_to_list(const struct rig_caps *rc, void* f);
    17  void populate_rigs_list();
    18  */
    19  import "C"
    20  
    21  import (
    22  	"errors"
    23  	"fmt"
    24  	"net/url"
    25  	"strconv"
    26  )
    27  
    28  var ErrUnknownModel = errors.New("Unknown rig model")
    29  
    30  // Rig represents a receiver or tranceiver.
    31  //
    32  // It holds the data connection to the device.
    33  type SerialRig struct{ r C.RIG }
    34  
    35  // VFO (Variable Frequency Oscillator) represents a tunable channel,
    36  // from the radio operator's view.
    37  //
    38  // Also referred to as "BAND" (A-band/B-band) by some radio manufacturers.
    39  type cVFO struct {
    40  	v C.vfo_t
    41  	r *SerialRig
    42  }
    43  
    44  var rigList []*C.struct_rig_caps
    45  
    46  func init() {
    47  	C.rig_set_debug(C.RIG_DEBUG_BUG)
    48  
    49  	rigList = make([]*C.struct_rig_caps, 0, 250)
    50  	C.populate_rigs_list()
    51  }
    52  
    53  //export rigListCb
    54  func rigListCb(rc *C.struct_rig_caps) {
    55  	rigList = append(rigList, rc)
    56  }
    57  
    58  // Rigs returns a map from RigModel to description (manufacturer and model)
    59  // of all known rigs.
    60  func Rigs() map[RigModel]string {
    61  	list := make(map[RigModel]string, len(rigList))
    62  	for _, rc := range rigList {
    63  		list[RigModel(rc.rig_model)] = fmt.Sprintf("%s %s",
    64  			C.GoString(rc.mfg_name),
    65  			C.GoString(rc.model_name))
    66  	}
    67  	return list
    68  }
    69  
    70  // OpenSerial connects to the transceiver and returns a ready to use Rig.
    71  //
    72  // Caller must remember to Close the Rig after use.
    73  func OpenSerial(model RigModel, path string, baudrate int) (*SerialRig, error) {
    74  	rig := C.rig_init(C.rig_model_t(model))
    75  	if rig == nil {
    76  		return nil, ErrUnknownModel
    77  	}
    78  
    79  	// Set baudrate
    80  	C.setBaudRate(rig, C.int(baudrate))
    81  
    82  	// Set path to tty
    83  	C.strncpy(&rig.state.rigport.pathname[0], C.CString(path), C.HAMLIB_FILPATHLEN-1)
    84  
    85  	err := codeToError(C.rig_open(rig))
    86  	if err != nil {
    87  		return nil, fmt.Errorf("Unable to open rig: %s", err)
    88  	}
    89  
    90  	return &SerialRig{*rig}, nil
    91  }
    92  
    93  // OpenSerialURI connects to the transceiver and returns a ready to use Rig.
    94  //
    95  // Expects a valid URI with path to a tty or COM-port.
    96  // Additional query parameters:
    97  //    model    (integer)
    98  //    baudrate (integer)
    99  // E.g. "/dev/ttyS0?model=123&baudrate=9600".
   100  //
   101  // Caller must remember to Close the Rig after use.
   102  func OpenSerialURI(uri string) (*SerialRig, error) {
   103  	u, err := url.Parse(uri)
   104  	if err != nil {
   105  		return nil, fmt.Errorf("Invalid address format")
   106  	}
   107  
   108  	modelStr := u.Query().Get("model")
   109  	if modelStr == "" {
   110  		return nil, fmt.Errorf("Missing model parameter")
   111  	}
   112  	model, err := strconv.Atoi(modelStr)
   113  	if err != nil {
   114  		return nil, fmt.Errorf("Invalid model format")
   115  	}
   116  
   117  	baudStr := u.Query().Get("baudrate")
   118  	if baudStr == "" {
   119  		return nil, fmt.Errorf("Missing baudrate parameter")
   120  	}
   121  	baudrate, err := strconv.Atoi(baudStr)
   122  	if err != nil {
   123  		return nil, fmt.Errorf("Invalid baudrate format")
   124  	}
   125  
   126  	return OpenSerial(RigModel(model), u.Path, baudrate)
   127  }
   128  
   129  // Closes the connection to the Rig.
   130  func (r *SerialRig) Close() error {
   131  	C.rig_close(&r.r)
   132  	return nil
   133  }
   134  
   135  // Returns the Rig's active VFO (for control).
   136  func (r *SerialRig) CurrentVFO() VFO {
   137  	return cVFO{C.RIG_VFO_CURR, r}
   138  }
   139  
   140  // Returns the Rig's A vfo.
   141  func (r *SerialRig) VFOA() (VFO, error) {
   142  	return cVFO{C.RIG_VFO_A, r}, nil
   143  }
   144  
   145  // Returns the Rig's B vfo.
   146  func (r *SerialRig) VFOB() (VFO, error) {
   147  	return cVFO{C.RIG_VFO_B, r}, nil
   148  }
   149  
   150  func (r *SerialRig) SetPowerState(pwr PowerState) error {
   151  	return codeToError(C.rig_set_powerstat(&r.r, C.powerstat_t(pwr)))
   152  }
   153  
   154  // Enable (or disable) PTT on this VFO.
   155  func (v cVFO) SetPTT(on bool) error {
   156  	var ns C.ptt_t
   157  	if on {
   158  		ns = C.RIG_PTT_ON
   159  	} else {
   160  		ns = C.RIG_PTT_OFF
   161  	}
   162  
   163  	return codeToError(C.rig_set_ptt(&v.r.r, v.v, ns))
   164  }
   165  
   166  // GetPTT returns the PTT state for this VFO.
   167  func (v cVFO) GetPTT() (bool, error) {
   168  	var ptt C.ptt_t
   169  	err := codeToError(C.rig_get_ptt(&v.r.r, v.v, &ptt))
   170  	return ptt == C.RIG_PTT_ON, err
   171  }
   172  
   173  // Sets the dial frequency for this VFO.
   174  func (v cVFO) SetFreq(freq int) error {
   175  	return codeToError(
   176  		C.rig_set_freq(&v.r.r, v.v, C.freq_t(freq)),
   177  	)
   178  }
   179  
   180  // Gets the dial frequency for this VFO.
   181  func (v cVFO) GetFreq() (int, error) {
   182  	var freq C.freq_t
   183  	err := codeToError(C.rig_get_freq(&v.r.r, v.v, &freq))
   184  	return int(freq), err
   185  }
   186  
   187  // SetMode switches to the given Mode using the supplied passband bandwidth.
   188  func (v cVFO) SetMode(m Mode, pbw int) error {
   189  	return codeToError(C.rig_set_mode(&v.r.r, v.v,
   190  		C.rmode_t(m),
   191  		C.pbwidth_t(pbw),
   192  	))
   193  }
   194  
   195  // GetMode returns this VFO's active Mode and passband bandwidth.
   196  func (v cVFO) GetMode() (m Mode, pwb int, err error) {
   197  	var cm C.rmode_t
   198  	var cpwb C.pbwidth_t
   199  	err = codeToError(C.rig_get_mode(&v.r.r, v.v, &cm, &cpwb))
   200  	return Mode(cm), int(cpwb), err
   201  }
   202  
   203  // Returns the narrow (closest) passband for the given Mode.
   204  func (r *SerialRig) PassbandNarrow(m Mode) int {
   205  	return int(C.rig_passband_narrow(&r.r, C.rmode_t(m)))
   206  }
   207  
   208  // Returns the normal (default) passband for the given Mode.
   209  func (r *SerialRig) PassbandNormal(m Mode) int {
   210  	return int(C.rig_passband_normal(&r.r, C.rmode_t(m)))
   211  }
   212  
   213  // Returns the wide (default) passband for the given Mode.
   214  func (r *SerialRig) PassbandWide(m Mode) int {
   215  	return int(C.rig_passband_wide(&r.r, C.rmode_t(m)))
   216  }
   217  
   218  func codeToError(code C.int) error {
   219  	if code == C.RIG_OK {
   220  		return nil
   221  	}
   222  	return errors.New(C.GoString(C.rigerror(code)))
   223  }