You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
5.0 KiB
250 lines
5.0 KiB
package comm
|
|
|
|
import (
|
|
"codeisalie/gono/cfg"
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
"regexp"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/tarm/serial"
|
|
)
|
|
|
|
const (
|
|
// SetPenDown ...
|
|
SetPenDown string = "C13"
|
|
// SetPenUp ... - args = 0
|
|
SetPenUp string = "C14"
|
|
// SetMachineSize saves machine width and height - args = 2
|
|
SetMachineSize string = "C24"
|
|
// SetMachineMmPerRev ... - args = 1
|
|
SetMachineMmPerRev string = "C29"
|
|
// SetMachineStepsPerRev ... - args = 1
|
|
SetMachineStepsPerRev string = "C30"
|
|
// SetMachineMotorSpeed ... - args = 1
|
|
SetMachineMotorSpeed string = "C31"
|
|
// SetMachineMotorAccel ... - args = 1
|
|
SetMachineMotorAccel string = "C32"
|
|
// SetMachineStepMultiplier ... - args = 1
|
|
SetMachineStepMultiplier string = "C37"
|
|
// GetMachineDetails ... - args = 0
|
|
GetMachineDetails string = "C26"
|
|
// DisableMotors ...
|
|
DisableMotors string = "CA0"
|
|
// EnableMotors ...
|
|
EnableMotors string = "CA1"
|
|
// DrawLine ... - args = 0
|
|
DrawLine string = "C17"
|
|
// DrawCircle ... - args = 0
|
|
DrawCircle string = "CB0"
|
|
// GetReportPosition ...
|
|
GetReportPosition string = "CC0"
|
|
)
|
|
|
|
// SetCMD saves one EEPROM command
|
|
type SetCMD struct {
|
|
Cmd string
|
|
Args []float64
|
|
}
|
|
|
|
// Comm context
|
|
type Comm struct {
|
|
isReady bool
|
|
mutex sync.Mutex
|
|
sync chan int
|
|
list chan string
|
|
com string
|
|
Cfg cfg.Config
|
|
serialCfg *serial.Config
|
|
handler *serial.Port
|
|
}
|
|
|
|
// Init returns an initialized serial handler
|
|
// Def: /dev/ttyACM0
|
|
func Init(com string, cfg cfg.Config) *Comm {
|
|
|
|
c := Comm{}
|
|
c.list = make(chan string)
|
|
c.sync = make(chan int)
|
|
c.Cfg = cfg
|
|
|
|
if com == "" {
|
|
com = "/dev/ttyACM0"
|
|
}
|
|
|
|
c.com = com
|
|
|
|
c.serialCfg = &serial.Config{Name: c.com, Baud: 57600}
|
|
handler, err := serial.OpenPort(c.serialCfg)
|
|
if err != nil {
|
|
log.Println(err)
|
|
return &c
|
|
}
|
|
|
|
log.Printf("[-] comm | %v opened\n", c.com)
|
|
|
|
c.handler = handler
|
|
|
|
go c.readSerial()
|
|
log.Printf("[-] comm | Waiting plotter stating\n")
|
|
<-c.sync
|
|
log.Printf("[-] comm | Plotter ready\n")
|
|
go c.sendMsg()
|
|
|
|
// q := make(chan os.Signal, 1)
|
|
// signal.Notify(q, os.Interrupt)
|
|
// go func() {
|
|
// for sig := range q {
|
|
// fmt.Println(sig)
|
|
// close(c.list)
|
|
// close(c.sync)
|
|
// }
|
|
// }()
|
|
|
|
return &c
|
|
}
|
|
|
|
// Queue one new message to send to serial interface
|
|
func (c *Comm) Queue(msg string) {
|
|
c.list <- msg
|
|
}
|
|
|
|
// Send ...
|
|
func (c *Comm) Send(cmd string, args ...float64) {
|
|
msg := cmd
|
|
switch cmd {
|
|
case DrawLine:
|
|
r1, r2 := c.convertCartToPolar(args[0], args[1])
|
|
args[0] = math.Floor(r1*100) / 100
|
|
args[1] = math.Floor(r2*100) / 100
|
|
}
|
|
for _, arg := range args {
|
|
msg += fmt.Sprintf(",%v", arg)
|
|
}
|
|
msg += ",END;"
|
|
// fmt.Println(msg)
|
|
c.Queue(msg)
|
|
}
|
|
|
|
// SendPPP one message to machine
|
|
func (c *Comm) SendPPP(cmd SetCMD) {
|
|
msg := cmd.Cmd
|
|
switch cmd.Cmd {
|
|
case DrawLine:
|
|
r1, r2 := c.convertCartToPolar(cmd.Args[0], cmd.Args[1])
|
|
cmd.Args[0] = r1
|
|
cmd.Args[1] = r2
|
|
}
|
|
for _, arg := range cmd.Args {
|
|
msg += fmt.Sprintf(",%v", arg)
|
|
}
|
|
msg += ",END;"
|
|
// fmt.Println(msg)
|
|
c.Queue(msg)
|
|
}
|
|
|
|
func (c *Comm) convertCartToPolar(x, y float64) (float64, float64) {
|
|
r1 := math.Sqrt(math.Pow(x, 2) + math.Pow(y, 2))
|
|
r2 := math.Sqrt(math.Pow(c.Cfg.MachineWidth-x, 2) + math.Pow(y, 2))
|
|
return r1, r2
|
|
}
|
|
|
|
// Send a message when it's serial com is ready
|
|
func (c *Comm) sendMsg() {
|
|
log.Printf("[-] comm | routine sendMsg started\n")
|
|
for {
|
|
<-c.sync
|
|
c.mutex.Lock()
|
|
c.isReady = true
|
|
c.mutex.Unlock()
|
|
time.Sleep(100 * time.Millisecond)
|
|
msg := <-c.list
|
|
log.Printf("[-] comm | Sending: %v\n", msg)
|
|
_, err := c.handler.Write([]byte(msg))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
} else {
|
|
// log.Println("written", n)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *Comm) GetIsReady() {
|
|
isReady := false
|
|
c.mutex.Lock()
|
|
isReady = c.isReady
|
|
c.mutex.Unlock()
|
|
|
|
return isReady
|
|
}
|
|
|
|
func (c *Comm) processSerialMsg(msg string) {
|
|
reReady := regexp.MustCompile("READY")
|
|
if reReady.MatchString(msg) {
|
|
c.sync <- 0
|
|
}
|
|
}
|
|
|
|
func (c *Comm) readSerial() {
|
|
log.Printf("[-] comm | routine readSerial started\n")
|
|
|
|
var char byte
|
|
var msg string
|
|
cr := byte('\r')
|
|
eol := byte('\n')
|
|
baf := make([]byte, 1)
|
|
buf := make([]byte, 128)
|
|
ptr := 0
|
|
for {
|
|
n, err := c.handler.Read(baf)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if n != 1 {
|
|
continue
|
|
}
|
|
|
|
char = baf[0]
|
|
|
|
if char == cr || char == eol {
|
|
if ptr > 0 {
|
|
msg = string(buf[:ptr])
|
|
fmt.Println(msg)
|
|
c.processSerialMsg(msg)
|
|
}
|
|
ptr = 0
|
|
} else {
|
|
buf[ptr] = char
|
|
ptr++
|
|
}
|
|
}
|
|
}
|
|
|
|
// codeReady := []byte("READY")
|
|
// reReady := regexp.MustCompile("READY")
|
|
// reSync := regexp.MustCompile("SYNC,(.*),(.*),END")
|
|
|
|
// n, err := s.Read(buf)
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
// msg := string(buf[:n])
|
|
// fmt.Printf("%v", msg)
|
|
|
|
// if reReady.Match(buf) {
|
|
// // fmt.Print("READY FROM RE")
|
|
// sync <- 0
|
|
// } else {
|
|
// // match := reSync.FindAllSubmatch(buf, -1)
|
|
// // if len(match) > 0 {
|
|
// // r1 := string(match[0][1])
|
|
// // r2 := string(match[0][2])
|
|
// // r1i, _ := strconv.Atoi(r1)
|
|
// // r2i, _ := strconv.Atoi(r2)
|
|
// // x, y := getXY(float64(r1i), float64(r2i))
|
|
// // fmt.Printf("R1: %v, R2:%v - X:%v - Y:%v\n", r1i, r2i, x, y)
|
|
// // }
|
|
// }
|