mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			154 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "lib/core/globals.h"
 | |
| #include "protocol.h"
 | |
| #include "lib/core/bytes.h"
 | |
| #include "lib/external/greaseweazle.h"
 | |
| 
 | |
| Bytes fluxEngineToGreaseweazle(const Bytes& fldata, nanoseconds_t clock)
 | |
| {
 | |
|     Bytes gwdata;
 | |
|     ByteWriter bw(gwdata);
 | |
|     ByteReader br(fldata);
 | |
|     uint32_t ticks_fl = 0;
 | |
|     uint32_t ticks_gw = 0;
 | |
| 
 | |
|     auto write_28 = [&](uint32_t val)
 | |
|     {
 | |
|         bw.write_8(1 | (val << 1) & 0xff);
 | |
|         bw.write_8(1 | (val >> 6) & 0xff);
 | |
|         bw.write_8(1 | (val >> 13) & 0xff);
 | |
|         bw.write_8(1 | (val >> 20) & 0xff);
 | |
|     };
 | |
| 
 | |
|     while (!br.eof())
 | |
|     {
 | |
|         uint8_t b = br.read_8();
 | |
|         ticks_fl += b & 0x3f;
 | |
|         if (b & F_BIT_PULSE)
 | |
|         {
 | |
|             uint32_t newticks_gw = ticks_fl * NS_PER_TICK / clock;
 | |
|             uint32_t delta = newticks_gw - ticks_gw;
 | |
|             if (delta < 250)
 | |
|                 bw.write_8(delta);
 | |
|             else
 | |
|             {
 | |
|                 int high = (delta - 250) / 255;
 | |
|                 if (high < 5)
 | |
|                 {
 | |
|                     bw.write_8(250 + high);
 | |
|                     bw.write_8(1 + (delta - 250) % 255);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     bw.write_8(255);
 | |
|                     bw.write_8(FLUXOP_SPACE);
 | |
|                     write_28(delta - 249);
 | |
|                     bw.write_8(249);
 | |
|                 }
 | |
|             }
 | |
|             ticks_gw = newticks_gw;
 | |
|         }
 | |
|     }
 | |
|     bw.write_8(0); /* end of stream */
 | |
|     return gwdata;
 | |
| }
 | |
| 
 | |
| Bytes greaseweazleToFluxEngine(const Bytes& gwdata, nanoseconds_t clock)
 | |
| {
 | |
|     Bytes fldata;
 | |
|     ByteReader br(gwdata);
 | |
|     ByteWriter bw(fldata);
 | |
| 
 | |
|     auto read_28 = [&]()
 | |
|     {
 | |
|         return ((br.read_8() & 0xfe) >> 1) | ((br.read_8() & 0xfe) << 6) |
 | |
|                ((br.read_8() & 0xfe) << 13) | ((br.read_8() & 0xfe) << 20);
 | |
|     };
 | |
| 
 | |
|     uint32_t ticks_gw = 0;
 | |
|     uint32_t lastevent_fl = 0;
 | |
|     uint32_t index_gw = ~0;
 | |
| 
 | |
|     while (!br.eof())
 | |
|     {
 | |
|         uint8_t b = br.read_8();
 | |
|         if (!b)
 | |
|             break;
 | |
| 
 | |
|         uint8_t event = 0;
 | |
|         if (b == 255)
 | |
|         {
 | |
|             switch (br.read_8())
 | |
|             {
 | |
|                 case FLUXOP_INDEX:
 | |
|                     index_gw = ticks_gw + read_28();
 | |
|                     break;
 | |
| 
 | |
|                 case FLUXOP_SPACE:
 | |
|                     ticks_gw += read_28();
 | |
|                     break;
 | |
| 
 | |
|                 default:
 | |
|                     error("bad opcode in Greaseweazle stream");
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (b < 250)
 | |
|                 ticks_gw += b;
 | |
|             else
 | |
|             {
 | |
|                 int delta = 250 + (b - 250) * 255 + br.read_8() - 1;
 | |
|                 ticks_gw += delta;
 | |
|             }
 | |
|             event = F_BIT_PULSE;
 | |
|         }
 | |
| 
 | |
|         if (event)
 | |
|         {
 | |
|             uint32_t index_fl = round((index_gw * clock) / NS_PER_TICK);
 | |
|             uint32_t ticks_fl = round((ticks_gw * clock) / NS_PER_TICK);
 | |
|             if (index_gw != ~0)
 | |
|             {
 | |
|                 if (index_fl < ticks_fl)
 | |
|                 {
 | |
|                     uint32_t delta_fl = index_fl - lastevent_fl;
 | |
|                     while (delta_fl > 0x3f)
 | |
|                     {
 | |
|                         bw.write_8(0x3f);
 | |
|                         delta_fl -= 0x3f;
 | |
|                     }
 | |
|                     bw.write_8(delta_fl | F_BIT_INDEX);
 | |
|                     lastevent_fl = index_fl;
 | |
|                     index_gw = ~0;
 | |
|                 }
 | |
|                 else if (index_fl == ticks_fl)
 | |
|                     event |= F_BIT_INDEX;
 | |
|             }
 | |
| 
 | |
|             uint32_t delta_fl = ticks_fl - lastevent_fl;
 | |
|             while (delta_fl > 0x3f)
 | |
|             {
 | |
|                 bw.write_8(0x3f);
 | |
|                 delta_fl -= 0x3f;
 | |
|             }
 | |
|             bw.write_8(delta_fl | event);
 | |
|             lastevent_fl = ticks_fl;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return fldata;
 | |
| }
 | |
| 
 | |
| /* Left-truncates at the first index mark, so the resulting data as aligned at
 | |
|  * the index. */
 | |
| Bytes stripPartialRotation(const Bytes& fldata)
 | |
| {
 | |
|     for (unsigned i = 0; i < fldata.size(); i++)
 | |
|     {
 | |
|         uint8_t b = fldata[i];
 | |
|         if (b & F_BIT_INDEX)
 | |
|             return fldata.slice(i);
 | |
|     }
 | |
|     return fldata;
 | |
| }
 |