c++/rgb-assembler/rgb-assembler.cpp
author František Kučera <franta-hg@frantovo.cz>
Sat, 23 Dec 2017 20:13:24 +0100
changeset 19 17785b69430d
parent 18 4975c24cc361
child 20 b9ceffdcaf14
permissions -rw-r--r--
move typedefs to a header file
     1 #include <cstdlib>
     2 #include <iostream>
     3 #include <wchar.h>
     4 #include <locale.h>
     5 #include <cstring>
     6 
     7 #include <chrono>
     8 #include <thread>
     9 
    10 #include "types.h"
    11 
    12 using namespace std;
    13 
    14 // TODO: strong typedefs http://www.boost.org/doc/libs/1_61_0/libs/serialization/doc/strong_typedef.html ?
    15 
    16 const address_t MEMORY_SIZE = 1024;
    17 
    18 /**
    19  * Skip to the given address.
    20  * parameter: address_t
    21  */
    22 const command_t CMD_GOTO = 0x70;
    23 
    24 /**
    25  * Compare values on two addresses and go to one of given three addresses.
    26  * parameter: address_t a
    27  * parameter: address_t b
    28  * parameter: address_t GOTO target when a == b
    29  * parameter: address_t GOTO target when a > b
    30  * parameter: address_t GOTO target when a < b
    31  */
    32 const command_t CMD_GOTO_COMPARE = 0x80;
    33 
    34 /**
    35  * Wait given time in ms.
    36  * parameter: sleep_t
    37  */
    38 const command_t CMD_SLEEP = 0xFF;
    39 
    40 /**
    41  * Set RGB LED color.
    42  * parameter: led_t LED number
    43  * parameter: color_t red
    44  * parameter: color_t green
    45  * parameter: color_t blue
    46  */
    47 const command_t CMD_COLOR = 0xAA;
    48 
    49 /**
    50  * Stop program.
    51  */
    52 const command_t CMD_END = 0xED;
    53 
    54 /**
    55  * Increase value at given address
    56  * parameter: address_t
    57  */
    58 const command_t CMD_INCREMENT = 0x11;
    59 
    60 /**
    61  * Decrease value at given address
    62  * parameter: address_t
    63  */
    64 const command_t CMD_DECREMENT = 0x12;
    65 
    66 /**
    67  * Placeholder for unsupported command.
    68  * Just for testing.
    69  */
    70 const command_t CMD_INVALID = 0x1;
    71 
    72 // TODO: more commands, better numbers
    73 
    74 template<typename T> T logMemoryError(const address_t &index) {
    75 	wprintf(L"memory error: index = %d, sizeof(T) = %d, MEMORY_SIZE = %d\n", index, sizeof (T), MEMORY_SIZE);
    76 	// TODO: return error value or throw exception
    77 	return T();
    78 }
    79 
    80 /**
    81  * Reads data on given position in memory and increments the index (position).
    82  * 
    83  * @param memory array of bytes / octets
    84  * @param index offset in same units as memory type
    85  * @return value found at given position
    86  */
    87 template<typename T> T read(octet_t * memory, address_t &index) {
    88 	// TODO: map higher memory to static hardcoded areas or peripherals
    89 	if (index + sizeof (T) <= MEMORY_SIZE) {
    90 		T * value = reinterpret_cast<T*> (memory + index);
    91 		index += sizeof (T);
    92 		return *value;
    93 	} else {
    94 		return logMemoryError<T>(index);
    95 	}
    96 }
    97 
    98 /**
    99  * Writes data to given position in memory and increments the index (position).
   100  * @param memory array of bytes / octets
   101  * @param index offset in same units as memory type
   102  * @param value value to be written at given position
   103  */
   104 template<typename T> T write(octet_t * memory, address_t &index, const T value) {
   105 	if (index + sizeof (T) <= MEMORY_SIZE) {
   106 		T * m = reinterpret_cast<T*> (memory + index);
   107 		*m = value;
   108 		index += sizeof (value);
   109 	} else {
   110 		return logMemoryError<T>(index);
   111 	}
   112 }
   113 
   114 int main(int argc, char* argv[]) {
   115 
   116 	setlocale(LC_ALL, "");
   117 
   118 	octet_t * memory = (octet_t*) malloc(MEMORY_SIZE);
   119 
   120 	// Sample program / data:
   121 	// TODO: load bytes from file, stdin, serial port, network…
   122 	{
   123 		address_t a = 0;
   124 		write<command_t>(memory, a, CMD_SLEEP);
   125 		write<sleep_t>(memory, a, 255);
   126 		write<command_t>(memory, a, CMD_SLEEP);
   127 		write<sleep_t>(memory, a, 10);
   128 		write<command_t>(memory, a, CMD_SLEEP);
   129 		write<sleep_t>(memory, a, 255);
   130 		write<command_t>(memory, a, CMD_GOTO);
   131 		write<address_t>(memory, a, a + sizeof (address_t) + 2 * sizeof (command_t));
   132 		write<command_t>(memory, a, CMD_INVALID);
   133 		write<command_t>(memory, a, CMD_INVALID);
   134 		write<command_t>(memory, a, CMD_SLEEP);
   135 		write<sleep_t>(memory, a, 255);
   136 		write<command_t>(memory, a, CMD_COLOR);
   137 		write<led_t>(memory, a, 23);
   138 		write<color_t>(memory, a, 0);
   139 		write<color_t>(memory, a, 200);
   140 		write<color_t>(memory, a, 255);
   141 		write<command_t>(memory, a, CMD_INCREMENT);
   142 		write<address_t>(memory, a, 0);
   143 		write<command_t>(memory, a, CMD_DECREMENT);
   144 		write<address_t>(memory, a, 0);
   145 		write<command_t>(memory, a, CMD_GOTO_COMPARE);
   146 		write<address_t>(memory, a, 0);
   147 		write<address_t>(memory, a, 0 + sizeof (command_t) + sizeof (sleep_t));
   148 		write<address_t>(memory, a, a - 3 * sizeof (address_t) - 2 * sizeof (command_t));
   149 		write<address_t>(memory, a, 0);
   150 		write<address_t>(memory, a, a + sizeof (address_t));
   151 		write<command_t>(memory, a, CMD_END);
   152 	}
   153 
   154 	for (address_t i = 0; i < MEMORY_SIZE;) {
   155 		wprintf(L"command %*d = ", 4, i);
   156 		command_t command = read<command_t>(memory, i);
   157 		wprintf(L"%02X  ", command);
   158 
   159 		switch (command) {
   160 			case CMD_GOTO:
   161 			{
   162 				i = read<address_t>(memory, i);
   163 				wprintf(L"GOTO %*d\n", 5, i);
   164 				break;
   165 			}
   166 			case CMD_SLEEP:
   167 			{
   168 				sleep_t delay = read<sleep_t>(memory, i);
   169 				wprintf(L"SLEEP %*d ms\n", 4, delay);
   170 				this_thread::sleep_for(chrono::milliseconds(delay));
   171 				break;
   172 			}
   173 			case CMD_COLOR:
   174 			{
   175 				led_t led = read<led_t>(memory, i);
   176 				color_t r = read<color_t>(memory, i);
   177 				color_t g = read<color_t>(memory, i);
   178 				color_t b = read<color_t>(memory, i);
   179 				wprintf(L"COLOR  %02X %02X %02X → %d\n", r, g, b, led);
   180 				break;
   181 			}
   182 			case CMD_INCREMENT:
   183 			case CMD_DECREMENT:
   184 			{
   185 				address_t address = read<address_t>(memory, i);
   186 				address_t address_r = address;
   187 				address_t address_w = address_r;
   188 				octet_t value = read<octet_t>(memory, address_r);
   189 				value = command == CMD_INCREMENT ? value + 1 : value - 1;
   190 				write<octet_t>(memory, address_w, value);
   191 				wprintf(L"%sCREMENT %*d → %02X\n", (command == CMD_INCREMENT ? "IN" : "DE"), 5, address, value);
   192 				break;
   193 			}
   194 			case CMD_GOTO_COMPARE:
   195 			{
   196 				address_t aa = read<address_t>(memory, i);
   197 				address_t ab = read<address_t>(memory, i);
   198 				address_t eq = read<address_t>(memory, i);
   199 				address_t gt = read<address_t>(memory, i);
   200 				address_t lt = read<address_t>(memory, i);
   201 
   202 				octet_t a = read<octet_t>(memory, aa);
   203 				octet_t b = read<octet_t>(memory, ab);
   204 
   205 				if (a == b) i = eq;
   206 				else if (a > b) i = gt;
   207 				else i = lt;
   208 
   209 				wprintf(L"GOTO COMPARE  a = %02X, b = %02X, eq = %d, gt = %d, lt = %d → %d\n", a, b, eq, gt, lt, i);
   210 				break;
   211 			}
   212 			case CMD_END:
   213 			{
   214 				wprintf(L"END\n");
   215 				i = MEMORY_SIZE;
   216 				break;
   217 			}
   218 			default:
   219 			{
   220 				wprintf(L"invalid command\n");
   221 			}
   222 		}
   223 
   224 	}
   225 
   226 	free(memory);
   227 	memory = nullptr;
   228 	wprintf(L"all done\n");
   229 	return 0;
   230 }
   231