gobot.io/x/gobot/v2@v2.1.0/platforms/neurosky/neurosky_driver.go (about) 1 package neurosky 2 3 import ( 4 "bytes" 5 6 "gobot.io/x/gobot/v2" 7 ) 8 9 const ( 10 // BTSync is the sync code 11 BTSync byte = 0xAA 12 13 // CodeEx Extended code 14 CodeEx byte = 0x55 15 16 // CodeSignalQuality POOR_SIGNAL quality 0-255 17 CodeSignalQuality byte = 0x02 18 19 // CodeAttention ATTENTION eSense 0-100 20 CodeAttention byte = 0x04 21 22 // CodeMeditation MEDITATION eSense 0-100 23 CodeMeditation byte = 0x05 24 25 // CodeBlink BLINK strength 0-255 26 CodeBlink byte = 0x16 27 28 // CodeWave RAW wave value: 2-byte big-endian 2s-complement 29 CodeWave byte = 0x80 30 31 // CodeAsicEEG ASIC EEG POWER 8 3-byte big-endian integers 32 CodeAsicEEG byte = 0x83 33 34 // Extended event 35 Extended = "extended" 36 37 // Signal event 38 Signal = "signal" 39 40 // Attention event 41 Attention = "attention" 42 43 // Meditation event 44 Meditation = "meditation" 45 46 // Blink event 47 Blink = "blink" 48 49 // Wave event 50 Wave = "wave" 51 52 // EEG event 53 EEG = "eeg" 54 55 // Error event 56 Error = "error" 57 ) 58 59 // Driver is the Gobot Driver for the Mindwave 60 type Driver struct { 61 name string 62 connection gobot.Connection 63 gobot.Eventer 64 } 65 66 // EEGData is the EEG raw data returned from the Mindwave 67 type EEGData struct { 68 Delta int 69 Theta int 70 LoAlpha int 71 HiAlpha int 72 LoBeta int 73 HiBeta int 74 LoGamma int 75 MidGamma int 76 } 77 78 // NewDriver creates a Neurosky Driver 79 // and adds the following events: 80 // 81 // extended - user's current extended level 82 // signal - shows signal strength 83 // attention - user's current attention level 84 // meditation - user's current meditation level 85 // blink - user's current blink level 86 // wave - shows wave data 87 // eeg - showing eeg data 88 func NewDriver(a *Adaptor) *Driver { 89 n := &Driver{ 90 name: "Neurosky", 91 connection: a, 92 Eventer: gobot.NewEventer(), 93 } 94 95 n.AddEvent(Extended) 96 n.AddEvent(Signal) 97 n.AddEvent(Attention) 98 n.AddEvent(Meditation) 99 n.AddEvent(Blink) 100 n.AddEvent(Wave) 101 n.AddEvent(EEG) 102 n.AddEvent(Error) 103 104 return n 105 } 106 107 // Connection returns the Driver's connection 108 func (n *Driver) Connection() gobot.Connection { return n.connection } 109 110 // Name returns the Driver name 111 func (n *Driver) Name() string { return n.name } 112 113 // SetName sets the Driver name 114 func (n *Driver) SetName(name string) { n.name = name } 115 116 // adaptor returns neurosky adaptor 117 func (n *Driver) adaptor() *Adaptor { 118 return n.Connection().(*Adaptor) 119 } 120 121 // Start creates a go routine to listen from serial port 122 // and parse buffer readings 123 func (n *Driver) Start() (err error) { 124 go func() { 125 for { 126 buff := make([]byte, 1024) 127 _, err := n.adaptor().sp.Read(buff[:]) 128 if err != nil { 129 n.Publish(n.Event("error"), err) 130 } else { 131 n.parse(bytes.NewBuffer(buff)) 132 } 133 } 134 }() 135 return 136 } 137 138 // Halt stops neurosky driver (void) 139 func (n *Driver) Halt() (err error) { return } 140 141 // parse converts bytes buffer into packets until no more data is present 142 func (n *Driver) parse(buf *bytes.Buffer) { 143 for buf.Len() > 2 { 144 b1, _ := buf.ReadByte() 145 b2, _ := buf.ReadByte() 146 if b1 == BTSync && b2 == BTSync { 147 length, _ := buf.ReadByte() 148 payload := make([]byte, length) 149 buf.Read(payload) 150 //checksum, _ := buf.ReadByte() 151 buf.Next(1) 152 n.parsePacket(bytes.NewBuffer(payload)) 153 } 154 } 155 } 156 157 // parsePacket publishes event according to data parsed 158 func (n *Driver) parsePacket(buf *bytes.Buffer) { 159 for buf.Len() > 0 { 160 b, _ := buf.ReadByte() 161 switch b { 162 case CodeEx: 163 n.Publish(n.Event("extended"), nil) 164 case CodeSignalQuality: 165 ret, _ := buf.ReadByte() 166 n.Publish(n.Event("signal"), ret) 167 case CodeAttention: 168 ret, _ := buf.ReadByte() 169 n.Publish(n.Event("attention"), ret) 170 case CodeMeditation: 171 ret, _ := buf.ReadByte() 172 n.Publish(n.Event("meditation"), ret) 173 case CodeBlink: 174 ret, _ := buf.ReadByte() 175 n.Publish(n.Event("blink"), ret) 176 case CodeWave: 177 buf.Next(1) 178 var ret = make([]byte, 2) 179 buf.Read(ret) 180 n.Publish(n.Event("wave"), int16(ret[0])<<8|int16(ret[1])) 181 case CodeAsicEEG: 182 ret := make([]byte, 25) 183 i, _ := buf.Read(ret) 184 if i == 25 { 185 n.Publish(n.Event("eeg"), n.parseEEG(ret)) 186 } 187 } 188 } 189 } 190 191 // parseEEG returns data converted into EEG map 192 func (n *Driver) parseEEG(data []byte) EEGData { 193 return EEGData{ 194 Delta: n.parse3ByteInteger(data[0:3]), 195 Theta: n.parse3ByteInteger(data[3:6]), 196 LoAlpha: n.parse3ByteInteger(data[6:9]), 197 HiAlpha: n.parse3ByteInteger(data[9:12]), 198 LoBeta: n.parse3ByteInteger(data[12:15]), 199 HiBeta: n.parse3ByteInteger(data[15:18]), 200 LoGamma: n.parse3ByteInteger(data[18:21]), 201 MidGamma: n.parse3ByteInteger(data[21:25]), 202 } 203 } 204 205 func (n *Driver) parse3ByteInteger(data []byte) int { 206 return ((int(data[0]) << 16) | 207 (((1 << 16) - 1) & (int(data[1]) << 8)) | 208 (((1 << 8) - 1) & int(data[2]))) 209 }