/// <summary> /// Connect, using optional drive name if present /// </summary> /// <param name="driveName"></param> private void Connect(string driveName = null) { lock (picLock) { if ((Device != null) && (Device.IsConnected)) { Device.Close(); Device = new HypnoLsdController(); return; } else { // try to connect Device.MessageReceived += BasicListener; Device.MessageReceived += BinaryListener; #if false Messages.Add("Faking connection - TODO - fix"); IsConnectedAndNotDrawing = !IsConnectedAndNotDrawing; IsConnected = !IsConnected; #else if (false == Device.Open(driveName)) { ShowMessageBox("Did not connect"); } else { ShowMessageBox("Needs fixing - check code"); //IsConnected = Device.IsConnected; //IsConnectedAndNotDrawing = isConnected; } #endif } } }
/// <summary> /// Send the buffer to the drawing mode buffer, then get the buffer back raw /// </summary> /// <param name="buffer"></param> /// <returns></returns> private byte[] RoundTripBuffer(byte[] buffer, HypnoLsdController device) { var mode = device.Drawing; if (mode) { device.Drawing = false; // exit to ensure at start of drawing buffer } Thread.Sleep(500); // give some time for above messages to return device.Drawing = true; Thread.Sleep(500); // give some time for above messages to return device.WriteBytes(buffer); Thread.Sleep(500); // give some time for above messages to return device.Drawing = false; Thread.Sleep(1000); // give some time for above messages to return device.MessageReceived += ByteListener; // get the buffer back recordedBytes = new ConcurrentQueue <byte>(); var start = new Stopwatch(); start.Start(); var lastSize = 0; var testLength = Math.Min(buffer.Length, device.RamSize); device.DumpRam((ushort)testLength); // read until timeout while (true) { if (start.ElapsedMilliseconds > 1000) { break; } if (lastSize != recordedBytes.Count) { // new data, reset timeout start.Restart(); lastSize = recordedBytes.Count; } } device.MessageReceived -= ByteListener; Thread.Sleep(500); var answer = recordedBytes.ToArray(); // clean message - remove final "OK\r\n"and initial message up to byte '\n' = 0x0A if (answer.Length > 0) { answer = answer.SkipWhile(b => b != '\n').Skip(1).Take(testLength).ToArray(); } device.Drawing = mode; Thread.Sleep(500); return(answer); }
/// <summary> /// Given a stream of bytes and image size, simulate the PIC image buffer /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="input">the sequence of bytes to simulate</param> /// <returns></returns> private byte[] StripeBuffer(HypnoLsdController device, int width, int height, byte[] input) { var buffer = new byte[device.RamSize]; int i1 = 0, j1 = 0, color = 0; // given a byte, and two bits, extract them, ith at position 4, jth at position 0, then shift Func <byte, int, int, int, byte> bits = (b, i, j, shift) => { var bi = (b >> i) & 1; var bj = (b >> j) & 1; return((byte)(((bi << 4) | bj) << shift)); }; Action <byte, int, int, int> write = (b, i, j, colr) => { var span = j / 625; var physicalJ = j % 625; var physicalI = i + width * span; var line = physicalI / 4; var shift = physicalI % 4; var offset = physicalJ * 48 + colr * 16 + 4 * line; // write to buffer at offset and next three positions // nibble pattern is 02461357 var mask = (byte)(~((1 << shift) + (1 << (shift + 4)))); buffer[offset + 0] = (byte)((buffer[offset + 0] & mask) | bits(b, 5, 7, shift)); // insert 5 and 7 bits buffer[offset + 1] = (byte)((buffer[offset + 1] & mask) | bits(b, 1, 3, shift)); // insert 1 and 3 bits buffer[offset + 2] = (byte)((buffer[offset + 2] & mask) | bits(b, 4, 6, shift)); // insert 4 and 6 bits buffer[offset + 3] = (byte)((buffer[offset + 3] & mask) | bits(b, 0, 2, shift)); // insert 0 and 2 bits }; var spans = (16 / width); var maxheight = spans * 625; foreach (var datum in input) { write(datum, i1, j1, color); color = (color + 1) % 3; // cycle RGB if (color == 0) { i1++; if (i1 == width) { i1 = 0; j1++; if (j1 == maxheight) { j1 = 0; } } } } return(buffer); }
internal void PutFile(HypnoLsdController device, string filename) { // read records until no more // a record is 128 bytes, // 1st byte is length N (0-126) of data bytes // then N data bytes (pad with 0 after N) // 128th byte is sum of bytes (checksum) // length 0 record with all 0 entries and 255 sum is end // after each record read correctly, returns 2 bytes: next record count mod 256 (0 based) and the checksum byte obtained // if record failed, resend with current record count mode 256 (asking for resend) and bit-inverted checksum byte var data = File.ReadAllBytes(filename); var block = new byte[128]; var pos = 0; // position of data to send device.WriteString("putfile \"" + Path.GetFileName(filename) + "\"\r\n"); Thread.Sleep(10); var len = 0; do { len = data.Length - pos; if (len > 126) { len = 126; } block[0] = (byte)len; var checksum = 0; for (var i = 0; i < len; ++i) { block[i + 1] = data[pos++]; checksum += block[i + 1]; } // 0 fill for (var i = len; i < 126; i++) { block[i + 1] = 0; } block[127] = (byte)checksum; // send 4 bytes at a time, with delays var temp = new byte[4]; for (var i = 0; i < block.Length; i += 4) { for (var j = 0; j < 4; ++j) { temp[j] = block[j + i]; } device.WriteBytes(temp); Thread.Sleep(1); } //device.WriteBytes(block); } while (len != 0); }
/// <summary> /// Set the default baud rate from the type /// </summary> /// <param name="devType"></param> private void ChangeDevice(Type devType) { // close any existing device if (Device != null) { Device.Close(); } Device = null; // todo - get from device var t = new HypnoLsdController(); BaudRate = t.DefaultBaudRate; }
/// <summary> /// Device changed, sets internals accordingly, /// </summary> private void DeviceChanged(HypnoLsdController oldDevice, HypnoLsdController newDevice) { if (oldDevice != null) { oldDevice.PropertyChanged -= DeviceOnPropertyChanged; } if (newDevice != null) { IsConnectedAndNotDrawing = Device.IsConnected && !device.Drawing; device.PropertyChanged += DeviceOnPropertyChanged; RamSize = newDevice.RamSize; PrepareSerialSpeeds(newDevice.PicClockSpeed); // todo - make baud rate of device chosen SelectedSpeed = SerialSpeeds[0]; ProcessReflection(newDevice.GetType()); ComputeRateParameters(newDevice.PicClockSpeed); } }
public void Start(HypnoLsdController device, Remapper remapper, int mbaud, Action <uint[]> imageFilterIn = null) { this.device = device; Remapper = remapper; Width = remapper.Width; Height = remapper.Height; if (imageFilterIn != null) { this.imageFilter = imageFilterIn; } else { this.imageFilter = b => { } }; // identity AddDemos(); // get attention device.WriteString("\r\n"); Thread.Sleep(250); //device.ConnectionSpeed = 1000000; // 1 Mbaud for testing //Thread.Sleep(100); //Thread.Sleep(1000); //device.Drawing = true; //Thread.Sleep(1000); //device.Drawing = false; //Thread.Sleep(1000); device.WriteString("\r\n"); device.ConnectionSpeed = mbaud; // 12000000;// 3000000;// 12000000; // 12 Mbaud for testing Thread.Sleep(500); const int delay = 200; device.Drawing = false; Thread.Sleep(delay); device.Drawing = true; Thread.Sleep(delay); device.Drawing = false; Thread.Sleep(delay); if (remapper.SupportedStrands.Contains(remapper.Strands)) { device.SetSize(remapper.Strands, remapper.Width * remapper.Height / remapper.Strands); } else { throw new NotImplementedException("Remapper does not support " + remapper.Strands + " strands"); } // some context switches to ensure we're at the top in case we disconnected early last time. device.Drawing = true; Thread.Sleep(delay); }
/// <summary> /// Do a test that the remote image buffer is getting the right /// byte structure in RAM when receiving bytes. /// </summary> /// <param name="device"></param> /// <param name="message"></param> public void TestImage(HypnoLsdController device, Action <string> message) { // fill buffer and test wraparound of buffer var buffer = new byte[device.RamSize + 1000]; // save these int w = device.ImageWidth, h = device.ImageHeight; // set to full size and zero it device.SetSize(16, 625); Thread.Sleep(500); // wait for above to settle // zero the buffer var returnedBytes = RoundTripBuffer(buffer, device); // amount expected back. Accounts for small and large wraparound buffers var testLength = Math.Min(buffer.Length, device.RamSize); // compare it var error = returnedBytes.Length != testLength; var errorCount = 0; if (!error) { for (var i = 0; i < returnedBytes.Length; ++i) { errorCount += buffer[i] != returnedBytes[i] ? 1 : 0; } } if (error || errorCount != 0) { message("Comparison error on zero image, " + errorCount + " places" + (errorCount == 0 ? ". " + returnedBytes.Length + " bytes bytes returned out of " + testLength : "") + "\n"); } else { message("No comparison error on zero image\n"); } // restore settings device.SetSize(w, h); // create legal random image. Remove sync bytes var rand = new Random(); rand.NextBytes(buffer); for (var i = 0; i < buffer.Length; ++i) { if (buffer[i] == 254) { buffer[i] = 255; } } // get the buffer back returnedBytes = RoundTripBuffer(buffer, device); // compare it error = returnedBytes.Length != testLength; errorCount = 0; byte[] packedBuffer = null; if (!error) { packedBuffer = StripeBuffer(device, w, h, buffer); for (var i = 0; i < testLength; ++i) { errorCount += packedBuffer[i] != returnedBytes[i] ? 1 : 0; } } if (error || errorCount != 0) { message("Comparison error on complex image, " + errorCount + " places" + (errorCount == 0 ? ". " + returnedBytes.Length + " bytes bytes returned out of " + testLength : "") + "\n"); } else { message("No comparison error on complex image\n"); } }
internal void GetFile(HypnoLsdController device, string filename) { }