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 }