-
Notifications
You must be signed in to change notification settings - Fork 76
/
platform_OSX.c
146 lines (117 loc) · 3.26 KB
/
platform_OSX.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
platform_LINUX.c - linux specific functions with generic cross-platform interface
Part of Grbl Simulator
Copyright (c) 2014 Adam Shelly
Grbl 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 3 of the License, or
(at your option) any later version.
Grbl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <time.h>
#include <sys/time.h>
#include "platform.h"
#define MS_PER_SEC 1000000
//any platform-specific setup that must be done before sim starts here
clock_serv_t cclock;
void platform_init() {
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
mach_timebase_info(&timebase);
conversion_factor = (double)timebase.numer / (double)timebase.denom;
}
//cleanup int here;
void platform_terminate()
{
mach_port_deallocate(mach_task_self(), cclock);
}
//returns a free-running 32 bit nanosecond counter which rolls over
uint32_t platform_ns()
{
static uint32_t gTimeBase = 0;
static uint32_t timestamp;
mach_timespec_t ts;
clock_get_time(cclock, &ts);
timestamp = ts.tv_sec*1e9+ts.tv_nsec;
if (gTimeBase== 0){gTimeBase=timestamp;}
return timestamp - gTimeBase;;
}
//sleep in microseconds
void platform_sleep(long microsec)
{
struct timespec ts={0};
while (microsec >= MS_PER_SEC){
ts.tv_sec++;
microsec-=MS_PER_SEC;
}
ts.tv_nsec = microsec*1000;
nanosleep(&ts,NULL);
}
#define SIM_ECHO_TERMINAL 1 //use this to make grbl_sim act like a serial terminal with local echo on.
//set terminal to allow kbhit detection
void enable_kbhit(int dir)
{
static struct termios oldt, newt;
if ( dir == 1 )
{
tcgetattr( STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~( ICANON );
if (!SIM_ECHO_TERMINAL) {
newt.c_lflag &= ~( ECHO );
}
tcsetattr( STDIN_FILENO, TCSANOW, &newt);
}
else
tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
}
//detect key pressed
int kbhit (void)
{
struct timeval tv={0};
fd_set rdfs={{0}};
int retval;
/* tv.tv_sec = 0; */
/* tv.tv_usec = 0; */
/* FD_ZERO(&rdfs); */
FD_SET (STDIN_FILENO, &rdfs);
select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv);
retval = FD_ISSET(STDIN_FILENO, &rdfs);
return retval;
}
plat_thread_t* platform_start_thread(plat_threadfunc_t threadfunc) {
plat_thread_t* th = malloc(sizeof(plat_thread_t));
if (pthread_create(&th->tid, NULL, threadfunc, &th->exit)){
free(th);
return NULL;
}
return th;
}
//ask thread to exit nicely, wait
void platform_stop_thread(plat_thread_t* th){
th->exit = 1;
pthread_join(th->tid,NULL);
}
//force-kill thread
void platform_kill_thread(plat_thread_t* th){
th->exit = 1;
pthread_cancel(th->tid);
}
//return char if one available.
uint8_t platform_poll_stdin() {
uint8_t char_in=0;
enable_kbhit(1);
if ( kbhit()) {
char_in = getchar();
}
enable_kbhit(0);
return char_in;
}