COMP1721 - Higher Computing 1B

Computing 1B - Week 11 Tutorial Solutions

  1. The I/O lines are in groups of 8 named Port A, Port B, .. Port F.

    Each group has 3 memory addresses associated with it. One address (named DDRx) can be used to set the I/O direction. A one written to a bit at that address makes the corresponding line an input, a 0 makes the corresponding line an output. For example for Port D, DDRD is address 0x31. So writing 0xF0 to address 0x31 would make PD0..PD3 output and PD4..PD7 inputs. One address (named PINx) can be used to read data from input lines. If the line is high (3 volts) the corresponding bit will be 1. If the line is low (0 volts) the corresponding bit will be 0. For example for Port D, PIND is address 0x30. One address (named PORTx) can be used to write data to output lines. If a bit is a one the corresponding line will be pulled high (3 volts). If a bit is a zero the corresponding line will be pulled low (0 volts). For example for Port D, PORTD is address 0x32.

  2. To delay for some time. This is called a busy wait.

    Its not a desirable on general purpose machine with multiple processes because it stop the CPU being used for other pusposes.

    A compiler might realize the loop is pointless and remove it.

  3. The gcc uses 16-bits on the AVR. They can store numbers in the range -32768..32767 Hence 50000 can't be represented as an int.

  4. Nothing. You must call uart_init() first to enable output via USB.

  5. #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct purchase purchase;
    typedef struct item     item;
    typedef double          price;
    typedef long            barcode;
    
    struct purchase {
        item        *what;
        int         how_many;
        purchase    *next;
    };
    
    struct item {
        char    *item_name;
        price   item_price;
        barcode item_barcode;
        item    *next;
    };
    
    enum {
        MAX_INPUT_LINE_LENGTH = 1024
    };
    
    void print_bill(purchase *purchase_list);
    purchase *add_purchase(barcode code, purchase *purchase_list, item *item_list);
    purchase *find_purchase(item *i, purchase *purchase_list);
    item *add_item(item *item_list);
    item *find_item(barcode code, item *item_list);
    void *salloc(size_t size);
    void read_to_newline(void);
    
    int
    main(void) {
        char command[MAX_INPUT_LINE_LENGTH];
        purchase *purchase_list = NULL;
        item *item_list = NULL;
        
        printf("Kensington Kwiki-Mart Billing System\n");
        while (1) {
            printf("Enter Command: ");
            if (fgets(command, MAX_INPUT_LINE_LENGTH, stdin) == NULL)
                return 0;
            
            if (strcmp(command,"bill\n") == 0) {
                while (1) {
                    barcode code;
                    printf("Enter barcode: ");
                    scanf("%ld", &code);
                    read_to_newline();
                    if (code == 0)
                        break;
                    purchase_list = add_purchase(code, purchase_list, item_list);
                }
              print_bill(purchase_list);
            } else if (strcmp(command, "price\n") == 0) {
                item_list = add_item(item_list);
            } else {
                printf("Unknown command - legal commands are bill and price\n");
            }
        }
        return 0;
    }
    
    void
    print_bill(purchase *purchase_list) {
        price total = 0;
        purchase *p;
        
        for (p = purchase_list; p != NULL; p = p->next) {
            price x = p->how_many * p->what->item_price;
            total += x;
            printf("%dx %s @$%.2f = $%.2f\n", p->how_many, p->what->item_name, p->what->item_price, x);
        }
    
        printf("Total: $%.2f\n", total);
        printf("Thank for Shopping at Kensington Kwiki-Mart\n");
    }
    
    
    purchase *
    add_purchase(barcode  code, purchase *purchase_list, item *item_list) {
        purchase *p;
        item     *i;
        
        i = find_item(code, item_list);
        if (i == NULL) {
            fprintf(stderr, "Unknown barcode\n");
            return purchase_list;
        }
        
        p = find_purchase(i, purchase_list);
        
        if (p != NULL) {
            p->how_many++;
            return purchase_list;
        }
        
        p = salloc(sizeof (purchase));
        p->what = i;
        p->how_many = 1;
        p->next = purchase_list;
        return p;
    }
    
    purchase *
    find_purchase(item *i, purchase *purchase_list) {
        purchase *p;
        
        for (p = purchase_list; p != NULL; p = p->next)
            if (p->what == i)
                return p;
        
        return NULL;
    }
    
    item *
    add_item(item *item_list) {
        barcode code;
        char    buffer[MAX_INPUT_LINE_LENGTH];
        item    *i;
        
        printf("Enter barcode: ");
        scanf("%ld", &code);
        read_to_newline();
        i = find_item(code, item_list);
    
        if (i != NULL) {
            printf("Enter new price for %s: ", i->item_name);
            scanf("%lf", &(i->item_price));
            read_to_newline();
            return item_list;
        }
        
        i = salloc(sizeof (item));
        i->item_barcode = code;
        printf("Enter name of the item: ");
        if (fgets(buffer, MAX_INPUT_LINE_LENGTH, stdin) == NULL || strlen(buffer) == 0) {
            fprintf(stderr, "Can not read name\n");
            exit(1);
        }
        buffer[strlen(buffer) - 1] = '\0'; /* remove '\n' */
        i->item_name = salloc(strlen(buffer) + 1);
        strcpy(i->item_name, buffer);
        printf("Enter price: ");
        scanf("%lf", &(i->item_price));
        read_to_newline();
        i->next = item_list;
        return i;
    }
        
    item *
    find_item(barcode code, item *item_list) {
        item *i;
        for (i = item_list; i != NULL; i = i->next) {
            if (i->item_barcode == code)
                return i;
        }
        return NULL;
    }
    
    void *
    salloc(size_t size) {
        void *m = malloc(size);
        if (m == NULL) {
            fprintf(stderr, "postcode_server: out of memory - attempting to malloc %d bytes\n", (int)size);
            exit(1);
        }
        return m;
    }
    
    void
    read_to_newline(void) {
        int c;
        while (1) {
            c = getchar();
            if (c == '\n' || c == EOF)
                return;
        }
    }
    


Andrew Taylor (andrewt@cse.unsw.edu.au)
Higher Computing 1B, Computer Science & Engineering, UNSW