   }
   pfun(')'); return;
 }
+
+// Assembler
+
+#if defined(CPU_ATmega1284P)
+#define CODE_ADDRESS 0x1bb00
+#elif defined(CPU_AVR128DX48)
+#define CODE_ADDRESS 0x1be00
+#endif
+
+#if defined(CODESIZE)
+object *call (int entry, int nargs, object *args, object *env) {
+  (void) env;
+  int param[4];
+  for (int i=0; i<nargs; i++) {
+    object *arg = first(args);
+    if (integerp(arg)) param[i] = arg->integer;
+    else param[i] = (uintptr_t)arg;
+    args = cdr(args);
+  }
+  uint32_t address = (CODE_ADDRESS + entry)>>1; // Code addresses are word addresses on AVR
+  int w = ((intfn_ptr_type)address)(param[0], param[1], param[2], param[3]);
+  return number(w);
+}
+
+void putcode (object *arg, int origin, int pc) {
+  int code = checkinteger(DEFCODE, arg);
+  uint8_t hi = (code>>8) & 0xff;
+  uint8_t lo = code & 0xff; 
+  MyCode[origin+pc] = lo;            // Little-endian
+  MyCode[origin+pc+1] = hi;
+  #if defined(assemblerlist)
+  printhex2(pc>>8, pserial); printhex2(pc, pserial); pserial(' ');
+  printhex2(lo, pserial); pserial(' '); printhex2(hi, pserial); pserial(' ');
+  #endif
+}
+
+int assemble (int pass, int origin, object *entries, object *env, object *pcpair) {
+  int pc = 0; cdr(pcpair) = number(pc);
+  while (entries != NULL) {
+    object *arg = first(entries);
+    if (symbolp(arg)) {
+      if (pass == 2) {
+        #if defined(assemblerlist)
+        printhex2(pc>>8, pserial); printhex2(pc, pserial);
+        pfstring(PSTR("       "), pserial);
+        printobject(arg, pserial); pln(pserial);
+        #endif
+      } else {
+        object *pair = findvalue(arg, env);
+        cdr(pair) = number(pc);
+      }
+    } else {
+      object *argval = eval(arg, env);
+      if (listp(argval)) {
+        object *arglist = argval;
+        while (arglist != NULL) {
+          if (pass == 2) {
+            putcode(first(arglist), origin, pc);
+            #if defined(assemblerlist)
+            if (arglist == argval) superprint(arg, 0, pserial);
+            pln(pserial);
+            #endif
+          }
+          pc = pc + 2;
+          cdr(pcpair) = number(pc);
+          arglist = cdr(arglist);
+        }
+      } else if (integerp(argval)) {
+        if (pass == 2) {
+          putcode(argval, origin, pc);
+          #if defined(assemblerlist)
+          superprint(arg, 0, pserial); pln(pserial);
+          #endif
+        }
+        pc = pc + 2;
+        cdr(pcpair) = number(pc);
+      } else error(DEFCODE, PSTR("illegal entry"), arg);
+    }
+    entries = cdr(entries);
+  }
+  // Round up to multiple of 2 to give code size
+  if (pc%2 != 0) pc = pc + 2 - pc%2;
+  return pc;
+}
+#endif
 
 // Special forms
 

  else if (streamtype == SPISTREAM) pfun = spiwrite;
  else if (streamtype == SERIALSTREAM) {
    if (address == 0) pfun = pserial;
    #if defined(CPU_ATmega1284P)
    else if (address == 1) pfun = serial1write;
    #elif defined(CPU_ATmega2560) || defined(CPU_AVR128DX48)
    else if (address == 1) pfun = serial1write;
    else if (address == 2) pfun = serial2write;
    else if (address == 3) pfun = serial3write;

  { string28, sp_withi2c, 0x1F },
  { string29, sp_withspi, 0x1F },
  { string30, sp_withsdcard, 0x2F },
  { string31, sp_defcode, 0x0F },
  { string32, NULL, 0x00 },
  { string33, tf_progn, 0x0F },
  { string34, tf_if, 0x23 },
  { string35, tf_cond, 0x0F },
  { string36, tf_when, 0x1F },
  { string37, tf_unless, 0x1F },
  { string38, tf_case, 0x1F },
  { string39, tf_and, 0x0F },
  { string40, NULL, 0x00 },
  { string41, fn_not, 0x11 },
  { string42, fn_not, 0x11 },
  { string43, fn_cons, 0x22 },
  { string44, fn_atom, 0x11 },
  { string45, fn_listp, 0x11 },
  { string46, fn_consp, 0x11 },
  { string47, fn_symbolp, 0x11 },
  { string48, fn_boundp, 0x11 },
  { string49, fn_setfn, 0x2F },
  { string50, fn_streamp, 0x11 },
  { string51, fn_eq, 0x22 },
  { string52, fn_car, 0x11 },
  { string53, fn_car, 0x11 },
  { string54, fn_cdr, 0x11 },
  { string55, fn_cdr, 0x11 },
  { string56, fn_caar, 0x11 },
  { string57, fn_cadr, 0x11 },
  { string58, fn_cadr, 0x11 },
  { string59, fn_cdar, 0x11 },
  { string60, fn_cddr, 0x11 },
  { string61, fn_caaar, 0x11 },
  { string62, fn_caadr, 0x11 },
  { string63, fn_cadar, 0x11 },
  { string64, fn_caddr, 0x11 },
  { string65, fn_caddr, 0x11 },
  { string66, fn_cdaar, 0x11 },
  { string67, fn_cdadr, 0x11 },
  { string68, fn_cddar, 0x11 },
  { string69, fn_cdddr, 0x11 },
  { string70, fn_length, 0x11 },
  { string71, fn_list, 0x0F },
  { string72, fn_reverse, 0x11 },
  { string73, fn_nth, 0x22 },
  { string74, fn_assoc, 0x22 },
  { string75, fn_member, 0x22 },
  { string76, fn_apply, 0x2F },
  { string77, fn_funcall, 0x1F },
  { string78, fn_append, 0x0F },
  { string79, fn_mapc, 0x2F },
  { string80, fn_mapcar, 0x2F },
  { string81, fn_mapcan, 0x2F },
  { string82, fn_add, 0x0F },
  { string83, fn_subtract, 0x1F },
  { string84, fn_multiply, 0x0F },
  { string85, fn_divide, 0x2F },
  { string86, fn_divide, 0x12 },
  { string87, fn_mod, 0x22 },
  { string88, fn_oneplus, 0x11 },
  { string89, fn_oneminus, 0x11 },
  { string90, fn_abs, 0x11 },
  { string91, fn_random, 0x11 },
  { string92, fn_maxfn, 0x1F },
  { string93, fn_minfn, 0x1F },
  { string94, fn_noteq, 0x1F },
  { string95, fn_numeq, 0x1F },
  { string96, fn_less, 0x1F },
  { string97, fn_lesseq, 0x1F },
  { string98, fn_greater, 0x1F },
  { string99, fn_greatereq, 0x1F },
  { string100, fn_plusp, 0x11 },
  { string101, fn_minusp, 0x11 },
  { string102, fn_zerop, 0x11 },
  { string103, fn_oddp, 0x11 },
  { string104, fn_evenp, 0x11 },
  { string105, fn_integerp, 0x11 },
  { string106, fn_integerp, 0x11 },
  { string107, fn_char, 0x22 },
  { string108, fn_charcode, 0x11 },
  { string109, fn_codechar, 0x11 },
  { string110, fn_characterp, 0x11 },
  { string111, fn_stringp, 0x11 },
  { string112, fn_stringeq, 0x22 },
  { string113, fn_stringless, 0x22 },
  { string114, fn_stringgreater, 0x22 },
  { string115, fn_sort, 0x22 },
  { string116, fn_stringfn, 0x11 },
  { string117, fn_concatenate, 0x1F },
  { string118, fn_subseq, 0x23 },
  { string119, fn_readfromstring, 0x11 },
  { string120, fn_princtostring, 0x11 },
  { string121, fn_prin1tostring, 0x11 },
  { string122, fn_logand, 0x0F },
  { string123, fn_logior, 0x0F },
  { string124, fn_logxor, 0x0F },
  { string125, fn_lognot, 0x11 },
  { string126, fn_ash, 0x22 },
  { string127, fn_logbitp, 0x22 },
  { string128, fn_eval, 0x11 },
  { string129, fn_globals, 0x00 },
  { string130, fn_locals, 0x00 },
  { string131, fn_makunbound, 0x11 },
  { string132, fn_break, 0x00 },
  { string133, fn_read, 0x01 },
  { string134, fn_prin1, 0x12 },
  { string135, fn_print, 0x12 },
  { string136, fn_princ, 0x12 },
  { string137, fn_terpri, 0x01 },
  { string138, fn_readbyte, 0x02 },
  { string139, fn_readline, 0x01 },
  { string140, fn_writebyte, 0x12 },
  { string141, fn_writestring, 0x12 },
  { string142, fn_writeline, 0x12 },
  { string143, fn_restarti2c, 0x12 },
  { string144, fn_gc, 0x00 },
  { string145, fn_room, 0x00 },
  { string146, fn_saveimage, 0x01 },
  { string147, fn_loadimage, 0x01 },
  { string148, fn_cls, 0x00 },
  { string149, fn_pinmode, 0x22 },
  { string150, fn_digitalread, 0x11 },
  { string151, fn_digitalwrite, 0x22 },
  { string152, fn_analogread, 0x11 },
  { string153, fn_analogreference, 0x11 },
  { string154, fn_analogreadresolution, 0x11 },
  { string155, fn_analogwrite, 0x22 },
  { string156, fn_dacreference, 0x11 },
  { string157, fn_delay, 0x11 },
  { string158, fn_millis, 0x00 },
  { string159, fn_sleep, 0x11 },
  { string160, fn_note, 0x03 },
  { string161, fn_edit, 0x11 },
  { string162, fn_pprint, 0x12 },
  { string163, fn_pprintall, 0x01 },
  { string164, fn_format, 0x2F },
  { string165, fn_require, 0x11 },
  { string166, fn_listlibrary, 0x00 },
  { string167, NULL, 0x00 },
#if defined(CPU_ATmega328P)
  { string168, (fn_ptr_type)HIGH, DIGITALWRITE },
  { string169, (fn_ptr_type)LOW, DIGITALWRITE },
  { string170, (fn_ptr_type)INPUT, PINMODE },
  { string171, (fn_ptr_type)INPUT_PULLUP, PINMODE },
  { string172, (fn_ptr_type)OUTPUT, PINMODE },
  { string173, (fn_ptr_type)DEFAULT, ANALOGREFERENCE },
  { string174, (fn_ptr_type)INTERNAL, ANALOGREFERENCE },
  { string175, (fn_ptr_type)EXTERNAL, ANALOGREFERENCE },
  { string176, NULL, 0x00 },
#elif defined(CPU_ATmega1284P)
  { string168, (fn_ptr_type)HIGH, DIGITALWRITE },
  { string169, (fn_ptr_type)LOW, DIGITALWRITE },
  { string170, (fn_ptr_type)INPUT, PINMODE },
  { string171, (fn_ptr_type)INPUT_PULLUP, PINMODE },
  { string172, (fn_ptr_type)OUTPUT, PINMODE },
  { string173, (fn_ptr_type)DEFAULT, ANALOGREFERENCE },
  { string174, (fn_ptr_type)INTERNAL1V1, ANALOGREFERENCE },
  { string175, (fn_ptr_type)INTERNAL2V56, ANALOGREFERENCE },
  { string176, (fn_ptr_type)EXTERNAL, ANALOGREFERENCE },
  { string177, NULL, 0x00 },
#elif defined(CPU_ATmega2560)
  { string168, (fn_ptr_type)HIGH, DIGITALWRITE },
  { string169, (fn_ptr_type)LOW, DIGITALWRITE },
  { string170, (fn_ptr_type)INPUT, PINMODE },
  { string171, (fn_ptr_type)INPUT_PULLUP, PINMODE },
  { string172, (fn_ptr_type)OUTPUT, PINMODE },
  { string173, (fn_ptr_type)DEFAULT, ANALOGREFERENCE },
  { string174, (fn_ptr_type)INTERNAL1V1, ANALOGREFERENCE },
  { string175, (fn_ptr_type)INTERNAL2V56, ANALOGREFERENCE },
  { string176, (fn_ptr_type)EXTERNAL, ANALOGREFERENCE },
  { string177, NULL, 0x00 },
#elif defined(CPU_ATmega4809)
  { string168, (fn_ptr_type)HIGH, DIGITALWRITE },
  { string169, (fn_ptr_type)LOW, DIGITALWRITE },
  { string170, (fn_ptr_type)INPUT, PINMODE },
  { string171, (fn_ptr_type)INPUT_PULLUP, PINMODE },
  { string172, (fn_ptr_type)OUTPUT, PINMODE },
  { string173, (fn_ptr_type)DEFAULT, ANALOGREFERENCE },
  { string174, (fn_ptr_type)INTERNAL, ANALOGREFERENCE },
  { string175, (fn_ptr_type)VDD, ANALOGREFERENCE },
  { string176, (fn_ptr_type)INTERNAL0V55, ANALOGREFERENCE },
  { string177, (fn_ptr_type)INTERNAL1V1, ANALOGREFERENCE },
  { string178, (fn_ptr_type)INTERNAL1V5, ANALOGREFERENCE },
  { string179, (fn_ptr_type)INTERNAL2V5, ANALOGREFERENCE },
  { string180, (fn_ptr_type)INTERNAL4V3, ANALOGREFERENCE },
  { string181, (fn_ptr_type)EXTERNAL, ANALOGREFERENCE },
  { string182, NULL, 0x00 },
#elif defined(CPU_AVR128DX48)
  { string168, (fn_ptr_type)HIGH, DIGITALWRITE },
  { string169, (fn_ptr_type)LOW, DIGITALWRITE },
  { string170, (fn_ptr_type)INPUT, PINMODE },
  { string171, (fn_ptr_type)INPUT_PULLUP, PINMODE },
  { string172, (fn_ptr_type)OUTPUT, PINMODE },
  { string173, (fn_ptr_type)DEFAULT, ANALOGREFERENCE },
  { string174, (fn_ptr_type)VDD, ANALOGREFERENCE },
  { string175, (fn_ptr_type)INTERNAL1V024, ANALOGREFERENCE },
  { string176, (fn_ptr_type)INTERNAL2V048, ANALOGREFERENCE },
  { string177, (fn_ptr_type)INTERNAL4V096, ANALOGREFERENCE },
  { string178, (fn_ptr_type)INTERNAL2V5, ANALOGREFERENCE },
  { string179, (fn_ptr_type)EXTERNAL, ANALOGREFERENCE },
  { string180, (fn_ptr_type)ADC_DAC0, ANALOGREAD },
  { string181, (fn_ptr_type)ADC_TEMPERATURE, ANALOGREAD },
  { string182, NULL, 0x00 },
#endif

// Insert your own table entries here
