AvaSmith-CodingSamples / C / BatterySimluation - C / batt_sim.c
batt_sim.c
Raw
// batt_sim.c: DO NOT MODIFY
//
// Battery display simulator support functions.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "batt.h"
#include <stdint.h>

#define BATT_MAX_BITS 30

// These global variables are documented in the header file
short BATT_VOLTAGE_PORT;
int32_t BATT_DISPLAY_PORT = 0;
unsigned char BATT_STATUS_PORT = 0;

// Convenience struct for representing the battery display  as characters 
typedef struct {
  char chars[7][32];
} batt_display;


// +-^^^-+                         0 
// |     |  #  #   ####  ####      1                 
// |     |  #  #      #     #      2                 
// |#####|  ####   ####  ####  V   3                 
// |#####|     #   #        #      4                 
// |#####|     # o ####  ####      5                    
// +-----+                         6
// 01234567890123456789012345678901                       
// 0         1         2         3                                 

// position of decimal place is at row 4, col 17

batt_display init_display = {
  .chars = {
    "+-^^^-+                        ", 
    "|     |                        ",                 
    "|     |                        ",                 
    "|     |                        ",                 
    "|     |                        ",                 
    "|     |                        ",                    
    "+-----+                        ",
  }
};

// Reset batt_display to be empty 
void reset_batt_display(batt_display *batt){
  *batt = init_display;
}  

// Print an batt_display 
void internal_print_batt_display(batt_display *batt){
  for(int i=0; i<7; i++){
    printf("%s\n",batt->chars[i]);
  }
}  

// Data and functions to set the state of the batt display 

// Position and char in display 
typedef struct {
  int r,c; int ch;
} charpos;
    
// Collection of characters corresponding to one bit in the state being set 
typedef struct {
  int len;                      // number of chars corresponding to this bit
  charpos pos[5];               // position of chars for this bit
} charpos_coll;

#define RGT 0
#define MID 6
#define LFT 13

// Correspondence of bit positions to which characters should be set 
charpos_coll bits2chars[BATT_MAX_BITS] = {
  { .len=1, .pos={{ 4,28,'%'}}                                      }, // 0
  { .len=1, .pos={{ 3,28,'V'}}                                      }, // 1
  { .len=1, .pos={{ 6,14,'o'}}                                      }, // 2

  { .len=4, .pos={{ 0,22 -RGT,'#'},{ 0,23 -RGT,'#'}, { 0,24 -RGT,'#'},{ 0,25 -RGT,'#'}} }, //  3 
  { .len=4, .pos={{ 0,25 -RGT,'#'},{ 1,25 -RGT,'#'}, { 2,25 -RGT,'#'},{ 3,25 -RGT,'#'}} }, //  4 
  { .len=4, .pos={{ 3,25 -RGT,'#'},{ 4,25 -RGT,'#'}, { 5,25 -RGT,'#'},{ 6,25 -RGT,'#'}} }, //  5 
  { .len=4, .pos={{ 6,22 -RGT,'#'},{ 6,23 -RGT,'#'}, { 6,24 -RGT,'#'},{ 6,25 -RGT,'#'}} }, //  6 
  { .len=4, .pos={{ 3,22 -RGT,'#'},{ 4,22 -RGT,'#'}, { 5,22 -RGT,'#'},{ 6,22 -RGT,'#'}} }, //  7 
  { .len=4, .pos={{ 0,22 -RGT,'#'},{ 1,22 -RGT,'#'}, { 2,22 -RGT,'#'},{ 3,22 -RGT,'#'}} }, //  8 
  { .len=4, .pos={{ 3,22 -RGT,'#'},{ 3,23 -RGT,'#'}, { 3,24 -RGT,'#'},{ 3,25 -RGT,'#'}} }, //  9 

  { .len=4, .pos={{ 0,22 -MID,'#'},{ 0,23 -MID,'#'}, { 0,24 -MID,'#'},{ 0,25 -MID,'#'}} }, // 10 
  { .len=4, .pos={{ 0,25 -MID,'#'},{ 1,25 -MID,'#'}, { 2,25 -MID,'#'},{ 3,25 -MID,'#'}} }, // 11 
  { .len=4, .pos={{ 3,25 -MID,'#'},{ 4,25 -MID,'#'}, { 5,25 -MID,'#'},{ 6,25 -MID,'#'}} }, // 12 
  { .len=4, .pos={{ 6,22 -MID,'#'},{ 6,23 -MID,'#'}, { 6,24 -MID,'#'},{ 6,25 -MID,'#'}} }, // 13 
  { .len=4, .pos={{ 3,22 -MID,'#'},{ 4,22 -MID,'#'}, { 5,22 -MID,'#'},{ 6,22 -MID,'#'}} }, // 14 
  { .len=4, .pos={{ 0,22 -MID,'#'},{ 1,22 -MID,'#'}, { 2,22 -MID,'#'},{ 3,22 -MID,'#'}} }, // 15 
  { .len=4, .pos={{ 3,22 -MID,'#'},{ 3,23 -MID,'#'}, { 3,24 -MID,'#'},{ 3,25 -MID,'#'}} }, // 16 

  { .len=4, .pos={{ 0,22 -LFT,'#'},{ 0,23 -LFT,'#'}, { 0,24 -LFT,'#'},{ 0,25 -LFT,'#'}} }, // 17 
  { .len=4, .pos={{ 0,25 -LFT,'#'},{ 1,25 -LFT,'#'}, { 2,25 -LFT,'#'},{ 3,25 -LFT,'#'}} }, // 18 
  { .len=4, .pos={{ 3,25 -LFT,'#'},{ 4,25 -LFT,'#'}, { 5,25 -LFT,'#'},{ 6,25 -LFT,'#'}} }, // 19 
  { .len=4, .pos={{ 6,22 -LFT,'#'},{ 6,23 -LFT,'#'}, { 6,24 -LFT,'#'},{ 6,25 -LFT,'#'}} }, // 20 
  { .len=4, .pos={{ 3,22 -LFT,'#'},{ 4,22 -LFT,'#'}, { 5,22 -LFT,'#'},{ 6,22 -LFT,'#'}} }, // 21 
  { .len=4, .pos={{ 0,22 -LFT,'#'},{ 1,22 -LFT,'#'}, { 2,22 -LFT,'#'},{ 3,22 -LFT,'#'}} }, // 22 
  { .len=4, .pos={{ 3,22 -LFT,'#'},{ 3,23 -LFT,'#'}, { 3,24 -LFT,'#'},{ 3,25 -LFT,'#'}} }, // 23 

  { .len=5,.pos={{5,1,'#'},{5,2,'#'},{5,3,'#'},{5,4,'#'},{5,5,'#'}} }, // 24
  { .len=5,.pos={{4,1,'#'},{4,2,'#'},{4,3,'#'},{4,4,'#'},{4,5,'#'}} }, // 25
  { .len=5,.pos={{3,1,'#'},{3,2,'#'},{3,3,'#'},{3,4,'#'},{3,5,'#'}} }, // 26
  { .len=5,.pos={{2,1,'#'},{2,2,'#'},{2,3,'#'},{2,4,'#'},{2,5,'#'}} }, // 27
  { .len=5,.pos={{1,1,'#'},{1,2,'#'},{1,3,'#'},{1,4,'#'},{1,5,'#'}} }, // 28
};


// Assumes ints are at least 32 bits for disp
void set_batt_display(batt_display *batt, int disp){
  int i,j;
  int mask = 0x1;
  reset_batt_display(batt);
  for(i=0; i<BATT_MAX_BITS; i++){
    //    printf("Checking %d\n",i);
    if( disp & (mask << i) ){ // ith bit set, fill in characters 
      //      printf("%d IS SET\n",i);
      charpos_coll coll = bits2chars[i];
      //      printf("Coll len: %d\n",coll.len);
      for(j=0; j<coll.len; j++){
        //        printf("Inner iter %d\n",j);
        charpos pos = coll.pos[j];
        batt->chars[pos.r][pos.c] = pos.ch;
        // print_batt_display(batt);
      }
    }
  }
}


// Use the global BATT_DISPLAY_PORT to print the battery display
void print_batt_display(){
  batt_display batt;
  set_batt_display(&batt, BATT_DISPLAY_PORT);
  internal_print_batt_display(&batt);
  return;
}



#define NCLUSTERS 6
int clusters[NCLUSTERS] = {
  3, 5, 7, 7, 7, 3
};

// Generate a string version of the bits which clusters the bits based
// on the logical groupings in the problem
char *bitstr(int x, int bits){
  static char buffer[512];
  int idx = 0;
  int clust_idx = 0;
  int clust_break = clusters[0];
  for(int i=0; i<bits; i++){
    if(i==clust_break){
      buffer[idx] = ' ';
      idx++;
      clust_idx++;
      clust_break += clusters[clust_idx];
    }
    buffer[idx] = x & (1 << (bits-i-1)) ? '1' : '0';
    idx++;
  }
  buffer[idx] = '\0';
  return buffer;
}

// Creates a string of bit indices matching the clustering pattern
// above
char *bitstr_index(int bits){
  static char buffer[512];
  char format[256];
  int pos = 0;
  int idx = bits;
  for(int i=0; i<NCLUSTERS; i++){
    idx -= clusters[i];
    if(clusters[i] > 1){
      sprintf(format, "%s%dd ","%",clusters[i]);
      pos += sprintf(buffer+pos, format, idx);
    }
    else{                       // cluster of 1 bit gets no index
      pos += sprintf(buffer+pos, "  ");
    }
  }
  buffer[pos-1] = '\0';         // eliminate trailing space
  return buffer;
}