Example #1
0
void
debug_print(Printer& p, Expr* e) {
  if (not e) {
    print(p, "()");
    return;
  }
  
  switch (e->kind) {
  // Names
  case basic_id: return debug_terminal(p, as<Basic_id>(e));
  case operator_id: return debug_operator(p, as<Operator_id>(e));
  case scoped_id: return debug_scoped(p, as<Scoped_id>(e));
  case indexed_id: return debug_indexed(p, as<Indexed_id>(e));
  case decl_id: return debug_id(p, as<Decl_id>(e));
  // Types
  case typename_type: return print(p, "typename");
  case unit_type: return print(p, "unit");
  case bool_type: return print(p, "bool");
  case nat_type: return print(p, "nat");
  case int_type: return print(p, "int");
  case char_type: return print(p, "char");
  case bitfield_type: return debug_ternary(p, as<Bitfield_type>(e));
  case fn_type: return debug_binary(p, as<Fn_type>(e));
  case range_type: return debug_unary(p, as<Range_type>(e));
  case record_type: return debug_nested_unary(p, as<Record_type>(e));
  case variant_type: return debug_nested_unary(p, as<Variant_type>(e));
  case dep_variant_type: return debug_nested_binary(p, as<Dep_variant_type>(e));
  case enum_type: return debug_nested_binary(p, as<Enum_type>(e));
  case array_type: return debug_binary(p, as<Array_type>(e));
  case dep_type: return debug_binary(p, as<Dep_type>(e));
  case module_type: return debug_module(p, as<Module>(e));
  // Networking primitives
  case net_str_type: return debug_unary(p, as<Net_str_type>(e));
  case net_seq_type: return debug_binary(p, as<Net_seq_type>(e));
  // Terms
  case unit_term: return print(p, "<unit>");
  case bool_term: return debug_terminal(p, as<Bool>(e));
  case int_term: return debug_terminal(p, as<Int>(e));
  case default_term: return print(p, "default");
  case fn_term: return debug_fn(p, as<Fn>(e));
  case builtin_term: return print(p, "<builtin>");
  case call_term: return debug_binary(p, as<Call>(e));
  case promo_term: return debug_binary(p, as<Promo>(e));
  case pred_term: return debug_binary(p, as<Pred>(e));
  case range_term: return debug_binary(p, as<Range>(e));
  case variant_term: return debug_binary(p, as<Variant>(e));
  case unary_term: return debug_binary(p, as<Unary>(e));
  case binary_term: return debug_ternary(p, as<Binary>(e));
  case if_term: return debug_ternary(p, as<If>(e));
  // Statements
  case block_stmt: return debug_nested_unary(p, as<Block>(e));
  case return_stmt: return debug_unary(p, as<Return>(e));
  // Declarations
  case top_decl: return debug_nested_unary(p, as<Top>(e));
  case def_decl: return debug_ternary(p, as<Def>(e));
  case parm_decl: return debug_ternary(p, as<Parm>(e));
  case field_decl: return debug_ternary(p, as<Field>(e));
  case alt_decl: return debug_binary(p, as<Alt>(e));
  case enum_decl: return debug_constructor(p, as<Enum>(e));
  case import_decl: return debug_unary(p, as<Import>(e));
  case using_decl: return debug_unary(p, as<Using>(e));
  // Unhandled
  default:
    // FIXME: Make a print formatter that gives complete information
    // about a node, including its class and id.
    steve_unreachable(format("debugging unhandled expression '{}'", node_name(e)));
  }
}
Example #2
0
/* How to use:
 * Do not call this directly, but use "stella_sync = UPDATE_VALUES" instead.
 * Purpose:
 * Sort channels' brightness values from high to low (and the
 * interrupt time points from low to high), to be able to switch on
 * channels one after the other depending on their brightness level
 * and point in time.
 * Implementation details:
 * Use a "linked list" to avoid expensive memory copies. Main difference
 * to a real linked list is, that all elements are already preallocated
 * on the stack and are not allocated on demand.
 * The function directly writes to a "just calculated"-structure and if we
 * want new values in the pwm interrupt, we just have to swap pointers from
 * the "interrupt save"-structure to the "just calculated"-structure. (The
 * meaning of both structures changes, too, of course.)
 * Although we provide each channel in the structure with its neccessary
 * information such as portmask and brightness level, we will actually
 * ignore brightness levels of 0% and 100% due to not linking them to the linked list.
 * 100%-level channels are switched on at the beginning of each
 * pwm cycle and not touched afterwards. Channels with same brightness
 * levels are merged together (their portmask at least).
 * */
static void
stella_sort()
{
  stella_timetable_entry_s *current, *last;
  uint8_t i;

  cal_table->head = 0;
  cal_table->port[0].mask = 0;
  cal_table->port[0].port = &STELLA_PORT1;
#ifdef STELLA_PINS_PORT2
  cal_table->port[1].mask = 0;
  cal_table->port[1].port = &STELLA_PORT2;
#endif

  for (i = 0; i < STELLA_CHANNELS; ++i)
  {
    /* set data of channel i */
    cal_table->channel[i].port.mask = _BV(i + STELLA_OFFSET_PORT1);
    cal_table->channel[i].port.port = &STELLA_PORT1;
#ifdef STELLA_PINS_PORT2
    if (i >= STELLA_PINS_PORT1)
    {
      cal_table->channel[i].port.mask =
        _BV((i - STELLA_PINS_PORT1) + STELLA_OFFSET_PORT2);
      cal_table->channel[i].port.port = &STELLA_PORT2;
    }
#endif
    cal_table->channel[i].value = 255 - stella_brightness[i];
    cal_table->channel[i].next = 0;

    /* Special case: 0% brightness (Don't include this channel!) */
    if (stella_brightness[i] == 0)
      continue;

    //cal_table->portmask |= _BV(i+STELLA_OFFSET);

    /* Special case: 100% brightness (Merge pwm cycle start masks! Don't include this channel!) */
    if (stella_brightness[i] == 255)
    {
#ifdef STELLA_PINS_PORT2
      if (i >= STELLA_PINS_PORT1)
        cal_table->port[1].mask |=
          _BV((i - STELLA_PINS_PORT1) + STELLA_OFFSET_PORT2);
      else
        cal_table->port[0].mask |= _BV(i + STELLA_OFFSET_PORT1);
#else
      cal_table->port[0].mask |= _BV(i + STELLA_OFFSET_PORT1);
#endif
      continue;
    }

    /* first item in linked list */
    if (!cal_table->head)
    {
      cal_table->head = &(cal_table->channel[i]);
      continue;
    }
    /* add to linked list with >=1 entries */
    current = cal_table->head;
    last = 0;
    while (current)
    {
      // same value as current item: do not add to linked list
      // but just update the portmask (DO THIS ONLY IF BOTH CHANNELS OPERATE ON THE SAME PORT)
      if (current->value == cal_table->channel[i].value &&
          current->port.port == cal_table->channel[i].port.port)
      {
#ifdef STELLA_PINS_PORT2
        if (i >= STELLA_PINS_PORT1)
          current->port.mask |=
            _BV((i - STELLA_PINS_PORT1) + STELLA_OFFSET_PORT2);
        else
          current->port.mask |= _BV(i + STELLA_OFFSET_PORT1);
#else
        current->port.mask |= _BV(i + STELLA_OFFSET_PORT1);
#endif
        break;
      }
      // insert our new value at the head of the list
      else if (!last && current->value > cal_table->channel[i].value)
      {
        cal_table->channel[i].next = cal_table->head;
        cal_table->head = &(cal_table->channel[i]);
        break;
      }
      // insert our new value somewhere in betweem
      else if (current->value > cal_table->channel[i].value)
      {
        cal_table->channel[i].next = last->next;
        last->next = &(cal_table->channel[i]);
        break;
      }
      // reached the end of the linked list: just append our new entry
      else if (!current->next)
      {
        current->next = &(cal_table->channel[i]);
        break;
      }
      // else go to the next item in the linked list
      else
      {
        last = current;
        current = current->next;
      }
    }
  }

#ifdef DEBUG_STELLA
  current = cal_table->head;
  while (current)
  {
    //debug_printf("%u %s\n", current->value, debug_binary(current->portmask));
    current = current->next;
  }
  debug_printf("Mask1: %s %u\n"
#ifdef STELLA_PINS_PORT2
               "Mask2: %s %u\n"
#endif
		  
               , debug_binary(stella_portmask[0]), stella_portmask[0]
#ifdef STELLA_PINS_PORT2
               , debug_binary(stella_portmask[1]), stella_portmask[1]
#endif
	      );
#endif

  /* Allow the interrupt to actually apply the calculated values */
  stella_sync = NEW_VALUES;
}
Example #3
0
/* How to use:
 * Do not call this directly, but use "stella_sync = UPDATE_VALUES" instead.
 * Purpose:
 * Sort channels' brightness values from high to low (and the
 * interrupt time points from low to high), to be able to switch on
 * channels one after the other depending on their brightness level
 * and point in time.
 * Implementation details:
 * Use a "linked list" to avoid expensive memory copies. Main difference
 * to a real linked list is, that all elements are already preallocated
 * on the stack and are not allocated on demand.
 * The function directly writes to a "just calculated"-structure and if we
 * want new values in the pwm interrupt, we just have to swap pointers from
 * the "interrupt save"-structure to the "just calculated"-structure. (The
 * meaning of both structures changes, too, of course.)
 * Although we provide each channel in the structure with its neccessary
 * information such as portmask and brightness level, we will actually
 * ignore brightness levels of 0% and 100% due to not linking them to the linked list.
 * 100%-level channels are only switched on at the beginning of each
 * pwm cycle and not touched afterwards. Channels with same brightness
 * levels are merged together (their portmask at least).
 * */
inline void
stella_sort()
{
	struct stella_timetable_entry* current, *last;
	uint8_t i;

	cal_table->portmask = 0;
	cal_table->head = 0;

	for (i=0;i<STELLA_PINS;++i)
	{
		/* set current item */
		cal_table->channel[i].portmask = _BV(i+STELLA_OFFSET);
		cal_table->channel[i].value = 255 - stella_brightness[i];
		cal_table->channel[i].next = 0;
		#ifdef STELLA_GAMMACORRECTION
		if (i<100)
			cal_table->channel[i].gamma_wait_cycles = pgm_read_byte(stella_gamma[i]);
		else
			cal_table->channel[i].gamma_wait_cycles = 0;
		cal_table->channel[i].gamma_wait_counter = cal_table->channel[i].gamma_wait_cycles;
		#endif

		/* Sepcial cases: 0% brightness */
		if (stella_brightness[i] == 0) continue;

		//cal_table->portmask |= _BV(i+STELLA_OFFSET);

		if (stella_brightness[i] == 255)
		{
			cal_table->portmask |= _BV(i+STELLA_OFFSET);
			continue;
		}

		/* first item in linked list */
		if (!cal_table->head)
		{
			cal_table->head = &(cal_table->channel[i]);
			continue;
		}
		/* add to linked list with >=1 entries */
		current = cal_table->head; last = 0;
		while (current)
		{
			// same value as current item: do not add to linked list
			// but just update the portmask
			if (current->value == cal_table->channel[i].value)
			{
				//current->portmask &= (uint8_t)~_BV(i+STELLA_OFFSET);
				current->portmask |= _BV(i+STELLA_OFFSET);
				break;
			}
			// insert our new value at the head of the list
			else if (!last && current->value > cal_table->channel[i].value)
			{
				cal_table->channel[i].next = cal_table->head;
				cal_table->head = &(cal_table->channel[i]);
				break;
			}
			// insert our new value somewhere in betweem
			else if (current->value > cal_table->channel[i].value)
			{
				cal_table->channel[i].next = last->next;
				last->next = &(cal_table->channel[i]);
				break;
			}
			// reached the end of the linked list: just add our new entry
			else if (!current->next)
			{
				current->next = &(cal_table->channel[i]);
				break;
			}
			// else go to the next item in the linked list
			else
			{
				last = current;
				current = current->next;
			}
		}
	}

	#ifdef DEBUG_STELLA
	// debug out
	current = cal_table->head;
	i = 0;
	while (current)
	{
		i++;
		debug_printf("%u %s\n", current->value, debug_binary(current->portmask));
		current = current->next;
	}
	debug_printf("%s %u\n", debug_binary(stella_portmask_neg), stella_portmask_neg);
	#endif

	/* Allow the interrupt to actually apply the calculated values */
	stella_sync = NEW_VALUES;
}