]> rtime.felk.cvut.cz Git - mf624-simulink.git/blobdiff - mf624_SIMULINK.c
mf624_blocks_demo adapt for IRC extension and include PWM blocks.
[mf624-simulink.git] / mf624_SIMULINK.c
index 51cca623ba87cb2456b20f042db59d70a4c9d00a..ebd22760240c5939ad75a629dcb5cf01c19b04ac 100644 (file)
@@ -1,8 +1,8 @@
-/* 
+/*
  * Application using MF624 UIO driver
- * 
- * Copyright (C) 2011 Rostislav Lisovy <lisovy@gmail.com> 
- * 
+ *
+ * Copyright (C) 2011 Rostislav Lisovy <lisovy@gmail.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -42,6 +42,7 @@
 #define UIO "uio0"
 
 mf624_state_t* mfst=NULL;
+unsigned mfst_refcnt = 0;
 
 static int bar_mapping_fill(bar_mapping_t *barmap, const char *uio_dev, int map_nr)
 {
@@ -111,6 +112,19 @@ static int bar_mapping_setup(bar_mapping_t *barmap, int device_fd)
        return 0;
 }
 
+static int bar_mapping_destroy(bar_mapping_t *barmap)
+{
+       off_t mmap_start;
+        size_t mmap_size;
+       size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
+
+       mmap_start = barmap->mmap_offset & ~page_mask;
+       mmap_size = barmap->mmap_offset + barmap->size + page_mask - mmap_start;
+       mmap_size &= ~page_mask;
+
+       return munmap(barmap->mmap_addr, mmap_size);
+}
+
 /****************************************************************/
 
 #define BUFF_SMALL             32
@@ -155,7 +169,7 @@ void DAC_enable(mf624_state_t* mfst)
                MFST2REG(mfst, 0, GPIOC_reg));
 }
 
-                            
+
 
 int DAC_write(mf624_state_t* mfst, dac_channel_t channel, int val)
 {
@@ -192,7 +206,7 @@ double ADC_read(mf624_state_t* mfst, adc_channel_t channel)
        mf624_read16(MFST2REG(mfst, 2, ADSTART_reg));
 
        // Check if conversion has finished
-       while((mf624_read32(MFST2REG(mfst, 0, GPIOC_reg)) & GPIOC_EOLC_mask)) { 
+       while((mf624_read32(MFST2REG(mfst, 0, GPIOC_reg)) & GPIOC_EOLC_mask)) {
                for (i = 0; i < 1000; i++) {} // small wait
        }
 
@@ -202,6 +216,16 @@ double ADC_read(mf624_state_t* mfst, adc_channel_t channel)
        return 10.0 * ((int16_t) (result << 2)) / (double) 0x8000;
 }
 
+extern uint32_t IRC_mode_change(mf624_state_t* mfst, uint32_t change_mask, uint32_t change_val)
+{
+       /* This sequence should be protected by mutex to protect changes in multirate systems */
+       mfst->IRC_mode = (mfst->IRC_mode & ~change_mask) | (change_val & change_mask);
+       mf624_write32(mfst->IRC_mode, MFST2REG(mfst, 4, IRCCTRL_reg));
+        /*printf("change_mask 0x%08x, change_val 0x%08x\n", change_mask, change_val);*/
+        /*printf("IRC mode set to %08lx\n", mfst->IRC_mode);*/
+       return mfst->IRC_mode;
+}
+
 
 static int open_device(char* path) {
        int device_fd;
@@ -345,7 +369,7 @@ static void run_simple_tests(char* dev_name)
                if (status != -1) {
                        printf(" Probably OK\n");
                }
-       
+
                printf("Tring to disable interrupts\n");
                status = disable_interrupts(device_fd);
                if (status != -1) {
@@ -408,15 +432,15 @@ static int mmap_regions(mf624_state_t* mfst)
 
 
 
-/** 
+/**
  * Try to initialize the MF624 UIO driver.
  *
  * If and only if S is not NULL and initialization fails, then
  * ssSetErrorStatus() gets called to report the error via Simulink
  * interface.
- * 
+ *
  * @param S Pointer to SimStruct for error reporting or NULL.
- * 
+ *
  * @return Zero in case of success, -1 in case of error.
  */
 int mf624_init(SimStruct *S)
@@ -436,8 +460,8 @@ int mf624_init(SimStruct *S)
                        if (S) ssSetErrorStatus(S,"/dev/" UIO ": mmap_regions failed");
                        goto close;
                }
-
        }
+       mfst_refcnt++;
        return 0;
 close:
        close(mfst->device_fd);
@@ -447,6 +471,40 @@ free:
        return -1;
 }
 
+int mf624_done()
+{
+       if (mfst) {
+               if (--mfst_refcnt == 0) {
+                       close(mfst->device_fd);
+                       bar_mapping_destroy(&mfst->bar0);
+                       bar_mapping_destroy(&mfst->bar2);
+                       bar_mapping_destroy(&mfst->bar4);
+                       free(mfst);
+                       mfst = NULL;
+               }
+       }
+
+       return 0;
+}
+
+
+/**
+ * Check whether MF624 card is initialized.
+ *
+ * @param S
+ *
+ * @return Zero if MF624 is initialized, -1 othewise.
+ */
+int mf624_check(SimStruct *S)
+{
+       if (mfst==NULL) {
+               if (S) ssSetErrorStatus(S, "MF624 is not initialized");
+               return -1;
+       }
+       else
+               return 0;
+}
+
 /*int main(int argc, char* argv[])
 {
        mf624_state_t* mfst = &mf624_state;
@@ -503,7 +561,7 @@ free:
                printf("Setting DA1 to 5 V\n");
                DAC_write(mfst, DA1, 0x3000);
                sleep(1);
-               
+
                printf("Reading ADC0: ");
                printf("%f V\n", ADC_read(mfst, AD0));
                sleep(1);