説明なし

receiver.go 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. package monitor
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "github.com/jacobsa/go-serial/serial"
  6. "io"
  7. "os"
  8. )
  9. const (
  10. MAXPACKETLLEN = 255 + 6
  11. )
  12. type Receiver struct {
  13. port io.ReadWriteCloser
  14. device string
  15. baud uint
  16. dataBits uint
  17. stopBits uint
  18. parity serial.ParityMode
  19. portConfig serial.OpenOptions
  20. receiverType ReceiverType
  21. Debug bool
  22. Dummy bool
  23. inMonitor bool
  24. seekPos uint32
  25. }
  26. func Connect(device string, baud int, dataBits int, stopBits int, parity string, debug bool) (*Receiver, error) {
  27. r := &Receiver{
  28. device: device,
  29. baud: uint(baud),
  30. dataBits: uint(dataBits),
  31. stopBits: uint(stopBits),
  32. Debug: debug,
  33. }
  34. r.portConfig = serial.OpenOptions{
  35. PortName: r.device,
  36. BaudRate: r.baud,
  37. DataBits: r.dataBits,
  38. StopBits: r.stopBits,
  39. MinimumReadSize: 0,
  40. InterCharacterTimeout: 1000, // a non-zero timeout is required for waitForMonitor to work
  41. }
  42. switch parity {
  43. case "none":
  44. r.parity = serial.PARITY_NONE
  45. r.portConfig.ParityMode = serial.PARITY_NONE
  46. case "even":
  47. r.parity = serial.PARITY_EVEN
  48. r.portConfig.ParityMode = serial.PARITY_EVEN
  49. case "odd":
  50. r.parity = serial.PARITY_ODD
  51. r.portConfig.ParityMode = serial.PARITY_ODD
  52. default:
  53. return nil, fmt.Errorf("unrecognized parity setting")
  54. }
  55. var err error
  56. r.port, err = serial.Open(r.portConfig)
  57. if err != nil {
  58. return nil, err
  59. }
  60. // figure out baud and parity
  61. err = r.ProbePortConfig()
  62. if err != nil {
  63. return nil, err
  64. }
  65. return r, nil
  66. }
  67. // ProbePortConfig probes different serial port settings to find a responding receiver
  68. func (r *Receiver) ProbePortConfig() error {
  69. var err error
  70. // First figure out what baud rate the receiver is currently set up for
  71. // easiest way to test this is by sending an ENQ
  72. for attempts := 0; attempts < 3; attempts++ {
  73. switch attempts {
  74. case 0:
  75. err = r.useUserBaudRate()
  76. case 1:
  77. err = r.useFastBaudRate()
  78. case 2:
  79. err = r.useSlowBaudRate()
  80. }
  81. if err != nil {
  82. return err
  83. }
  84. err = r.ClearComm()
  85. if err != nil {
  86. return err
  87. }
  88. ok, err := r.EnqAckTest()
  89. if err != nil {
  90. return err
  91. }
  92. if !ok {
  93. continue
  94. }
  95. if ok {
  96. return nil
  97. }
  98. }
  99. return fmt.Errorf("can't find receiver")
  100. }
  101. func (r *Receiver) reconfigurePort(baudRate uint, dataBits uint, stopBits uint, parity serial.ParityMode) error {
  102. var err error
  103. r.port.Close()
  104. r.portConfig.BaudRate = baudRate
  105. r.portConfig.DataBits = dataBits
  106. r.portConfig.StopBits = stopBits
  107. r.portConfig.ParityMode = parity
  108. r.port, err = serial.Open(r.portConfig)
  109. return err
  110. }
  111. func (r *Receiver) useSlowBaudRate() error {
  112. fmt.Println("Reconfiguring port to slow monitor baud rate: 9600 n-8-1")
  113. return r.reconfigurePort(9600, 8, 1, serial.PARITY_NONE)
  114. }
  115. func (r *Receiver) useFastBaudRate() error {
  116. fmt.Println("Reconfiguring port to fast baud rate: 38400 n-8-1")
  117. // return r.reconfigurePort(38400, 8, 1, serial.PARITY_NONE)
  118. return r.reconfigurePort(38400, 8, 1, serial.PARITY_ODD)
  119. }
  120. func (r *Receiver) useUserBaudRate() error {
  121. fmt.Printf("Reconfiguring port to user baud rate: %d %s-%d-%d\n", r.baud, parityToString(r.parity), r.dataBits, r.stopBits)
  122. return r.reconfigurePort(r.baud, r.dataBits, r.stopBits, r.parity)
  123. }
  124. func parityToString(p serial.ParityMode) string {
  125. s := []string{"none", "odd", "even"}
  126. return s[p]
  127. }
  128. // ClearComm sents 249 nulls on the serial port, which is something trimble likes to
  129. // do when starting the monitor. I think the point of this was to flush out the FIFO
  130. // buffers.
  131. func (r *Receiver) ClearComm() error {
  132. nulls := make([]byte, 249)
  133. _, err := r.Write(nulls)
  134. if err != nil {
  135. return err
  136. }
  137. // b := make([]byte, 12000)
  138. // n, _ := m.Read(b)
  139. // fmt.Printf("%d %02X \n",n,b)
  140. x := r.port.(*os.File) // TODO: verify if this is actually needed
  141. x.Sync()
  142. return nil
  143. }
  144. func (r *Receiver) FlushInput() {
  145. b := make([]byte, 12000)
  146. for {
  147. n, _ := r.Read(b)
  148. fmt.Printf("FLUSH read %d bytes: % 02X\n", n, b[:n])
  149. if n == 0 {
  150. return
  151. }
  152. }
  153. }
  154. // Write is wrapped so that debug messages can be printed
  155. func (r *Receiver) Write(b []byte) (int, error) {
  156. r.debugLog("Port Write: % 02X", b)
  157. //fmt.Printf("%02X••\n",b)
  158. if r.Dummy {
  159. return len(b), nil
  160. }
  161. n, err := r.port.Write(b)
  162. return n, err
  163. }
  164. // Read is wrapped so that debug messages can be printed
  165. func (r *Receiver) Read(b []byte) (int, error) {
  166. n, err := r.port.Read(b)
  167. if err == nil {
  168. r.debugLog("Port Read: % 02X", b)
  169. }
  170. return n, err
  171. }
  172. // ReadFull is wrapped so that debug messages can be printed
  173. func (r *Receiver) ReadFull(b []byte) (int, error) {
  174. n, err := io.ReadFull(r.port, b)
  175. if err == nil {
  176. r.debugLog("Port ReadFull: % 02X", b)
  177. }
  178. return n, err
  179. }
  180. func (r *Receiver) debugLog(format string, a ...interface{}) {
  181. if r.Debug {
  182. fmt.Printf(" "+format+"\n", a...)
  183. }
  184. }
  185. // waitForMonitor blocks until the receiver has entered monitor mode.
  186. // It can take a while for the receiver to boot into monitor mode, this
  187. // function tests the state of the receiver by repeatedly sending an ENQ
  188. // command. When the monitor is ready, it will send an ACK.
  189. func (r *Receiver) waitForMonitor() error {
  190. fmt.Println("Waiting for monitor to become ready...")
  191. for i := 0; i < 30; i++ {
  192. if ok, err := r.EnqAckTest(); ok {
  193. return nil
  194. } else if err != nil {
  195. return err
  196. }
  197. }
  198. return fmt.Errorf("timed out waiting for monitor")
  199. }
  200. // ProbeReceiverState checks if the receiver is in normal mode or monitor mode.
  201. // this is done by running command 0x82, which in normal mode is the screen dump
  202. // command, which replies with a packet of type 0x82. In monitor mode, the
  203. // command replies with a packet of type 0x92. If the receiver responds with
  204. // a 0x92 packet, we know it's in monitor mode.
  205. func (r *Receiver) ProbeReceiverState() (ReceiverState, error) {
  206. fmt.Println("Preforming dummy read to determine monitor state...")
  207. b := make([]byte, 5)
  208. binary.BigEndian.PutUint32(b[0:], 0x80000) // 'safe' dummy location to read from, I think it's the RAM base address
  209. b[4] = 2 // read 2 bytes
  210. reply, err := r.DoStxEtxCommand(MonCmdReadMem, b)
  211. if err != nil {
  212. return ReceiverUnresponsive, err
  213. }
  214. if reply.Command == MonCmdReadMemAck && reply.Status == 0 {
  215. fmt.Println("Receiver appears to be in monitor mode.")
  216. return ReceiverInMonitor, nil
  217. }
  218. fmt.Println("Receiver appears to be in normal mode.")
  219. return ReceiverNormal, nil
  220. }
  221. type ProtocolError struct {
  222. err string
  223. }
  224. func newProtocolError(format string, a ...interface{}) error {
  225. return &ProtocolError{err: fmt.Sprintf(format, a...)}
  226. }
  227. func (e *ProtocolError) Error() string {
  228. return e.err
  229. }
  230. func (r *Receiver) EnqAckTest() (bool, error) {
  231. buf := make([]byte, 1)
  232. r.Write([]byte{0x05}) // enq
  233. n, err := r.Read(buf)
  234. if err == nil && n > 0 && buf[0] == 0x06 { // ack
  235. return true, nil
  236. } else {
  237. if err != io.EOF {
  238. return false, err
  239. }
  240. }
  241. return false, nil
  242. }
  243. // DoAckCommand sends an STX/ETX framed command that expects a single byte reply. Sometimes
  244. // it's not an ACK that's sent, so it's up to the caller to tell this function what it
  245. // response it expects.
  246. func (r *Receiver) DoAckCommand(command byte, data []byte) error {
  247. err := r.SendStxEtxRequest(command, data)
  248. if err != nil {
  249. return err
  250. }
  251. if r.Dummy {
  252. return nil
  253. }
  254. return r.ReadAckReply()
  255. }
  256. // ReadAckReply reads a single byte reply
  257. func (r *Receiver) ReadAckReply() error {
  258. reply := make([]byte, 1)
  259. n, err := r.Read(reply)
  260. if err != nil {
  261. return err
  262. }
  263. if n != 1 || reply[0] != 0x06 { // ack
  264. return newProtocolError("ack not received")
  265. }
  266. return nil
  267. }
  268. type CommandReply struct {
  269. Status byte
  270. Command byte
  271. Data []byte
  272. }
  273. // DoStxEtxCommand sends an STX/ETX framed command that expects an STX/ETX framed reply
  274. func (r *Receiver) DoStxEtxCommand(command byte, data []byte) (*CommandReply, error) {
  275. err := r.SendStxEtxRequest(command, data)
  276. if err != nil {
  277. return nil, err
  278. }
  279. reply, err := r.ReadStxEtxReply()
  280. if err != nil {
  281. return nil, err
  282. }
  283. return reply, nil
  284. }
  285. // SendStxEtxRequest sends an STX/ETX framed request
  286. func (r *Receiver) SendStxEtxRequest(command byte, data []byte) error {
  287. payload := []byte{0, command, byte(len(data))}
  288. payload = append(payload, data...)
  289. var checksum byte
  290. for _, b := range payload {
  291. checksum += b
  292. }
  293. packet := append([]byte{0x02}, payload...) // stx
  294. packet = append(packet, []byte{checksum, 0x03}...) // etx
  295. _, err := r.Write(packet)
  296. return err
  297. }
  298. // ReadStxEtxReply reads a STX/ETX framed reply
  299. func (r *Receiver) ReadStxEtxReply() (*CommandReply, error) {
  300. packet := make([]byte, MAXPACKETLLEN) // maximum packet length
  301. _, err := r.ReadFull(packet[:4])
  302. if err != nil {
  303. return nil, err
  304. }
  305. if packet[0] != 0x02 { // stx
  306. fmt.Printf("expected STX received: %02X\n", packet[0])
  307. return nil, newProtocolError("expected STX received: %02X", packet[0])
  308. }
  309. status := packet[1]
  310. command := packet[2]
  311. length := int(packet[3])
  312. _, err = r.ReadFull(packet[4 : length+6]) // also read checksum and ETX
  313. packet = packet[:length+6] // trim to length
  314. checksum := packet[len(packet)-2]
  315. var computedChecksum byte
  316. for _, b := range packet[1 : len(packet)-2] {
  317. computedChecksum += b
  318. }
  319. if checksum != computedChecksum {
  320. return nil, newProtocolError("bad checksum. received: %02X expected: %02X", checksum, computedChecksum)
  321. }
  322. if packet[len(packet)-1] != 0x03 { // etx
  323. return nil, newProtocolError("expected ETX received: %02X", packet[len(packet)-1])
  324. }
  325. return &CommandReply{
  326. Status: status,
  327. Command: command,
  328. Data: packet[4 : len(packet)-2],
  329. }, nil
  330. }