summaryrefslogtreecommitdiff
path: root/tek.go
blob: cce0beb5777562e2349e183716604f9e5fb1474a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main

import (
	"io"
	"os"
)

const (
	FF  = 12
	ESC = 27
	FS  = 28 // point plot
	GS  = 29 // graph and dark vector
	RS  = 30 // incremental plot
	US  = 31 // alpha mode
)

type Out struct {
	io.Writer
	hx, hy, lx, ly, eb byte
	xterm              bool
	height, width      int
}

func (o *Out) escString(s string) {
	o.Write([]byte{ESC})
	o.Write([]byte(s))
}

func (o *Out) writeByte(b ...byte) {
	o.Write(b)
}

func NewOut(w io.Writer) *Out {
	return &Out{
		Writer: w,
		xterm:  os.Getenv("TERM") == "xterm",
		height: 3072,
		width:  4096,
	}
}

func (o Out) Clear() {
	o.writeByte(ESC, FF) // Tek Page
}

func (o Out) Enable() {
	if o.xterm {
		o.escString("[?38h")
	}
	o.Clear()
}

func (o Out) Disable() {
	o.writeByte(US) // Text mode
	if o.xterm {
		o.writeByte(ESC, 3) // VT Page
	}
}

func (o Out) Pen() {
	o.writeByte(GS)
}

func limit(val, max int) int {
	if val < 0 {
		return 0
	}
	if val >= max {
		return max - 1
	}
	return val
}

func (o *Out) Dim() (w, h int) {
	return o.width, o.height
}

// Table 13-4 Bytes Values for Encoding Coordinates
// 		Tag Bits	Address Bits
// Byte Name 	7	6	5	4	3	2	1
// High Y	0	1	5 most significant bits of Y address
// Extra	1	1		Y2	Y1	X2	X1
// Low Y	1	1	5 intermediate bits of Y address
// High X	0	1	5 most significant bits of X address
// Low X	1	0	5 intermediate bits of X address

// Table 13-5 Rules for Sending Short Address
// Bytes Changed	Bytes Sent
// 			High Y	Extra	Low Y	High X	Low X
// High Y		Yes	No	No	No	Yes
// Extra		No	Yes	Yes	No	Yes
// Low Y		No	No	Yes	No	Yes
// High X		No	No	Yes	Yes	Yes
// Low X		No	No	No	No	Yes

// Ref: http://www.vt100.net/docs/vt3xx-gp/chapter13.html

func (o *Out) Plot(x, y int) {
	x = limit(x, o.width)
	y = limit(y, o.height)

	hy := byte(y>>7) & 0x1f
	eb := (byte(y&3) << 2) | byte(x&3)
	ly := byte(y>>2) & 0x1f
	hx := byte(x>>7) & 0x1f
	lx := byte(x>>2) & 0x1f

	if hy != o.hy {
		o.writeByte(0x20 | hy)
	}
	if eb != o.eb {
		o.writeByte(0x60 | eb)
	}
	if ly != o.ly || eb != o.eb || hx != o.hx {
		o.writeByte(0x60 | ly)
	}
	if hx != o.hx {
		o.writeByte(0x20 | hx)
	}
	o.writeByte(0x40 | lx)

	o.hy = hy
	o.eb = eb
	o.ly = ly
	o.hx = hx
	o.lx = lx
}