Plotter code
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

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)
// // }
// }